0

I decomposed the spectrogram from an audio file like this:

import librosa
y, sr = librosa.load('my audio file.wav')
S = np.abs(librosa.stft(y))
W, H = librosa.decompose.decompose(S, n_components=32) 

Now how to recompose the decomposed spectrogram to actual spectogram.

What i want is like this type of functionality:

S=recompose(W,H)
Amin Pial
  • 383
  • 6
  • 12
  • Possible duplicate of [How to convert a .wav file to a spectrogram in python3](https://stackoverflow.com/questions/44787437/how-to-convert-a-wav-file-to-a-spectrogram-in-python3) – amirhosein majidi Sep 02 '18 at 07:36
  • with due respect this is no way a duplicate.I already solved that problem and come to this point to reverse that result.That's why already gave my code sample to convert wav to spectogram.But mu question is after decomposing that spectogram how do i recompose it.So that's 2 way advance than the issue you mentioned.Btw thanks. – Amin Pial Sep 02 '18 at 08:50

1 Answers1

0

The returned result is a linear decomposition into activation and components. We can go the other way using the dot product of these two.

import librosa
import numpy
import sklearn.decomposition

filename = librosa.util.example_audio_file()
y, sr = librosa.load(filename)
y = y[:20000] # smaller file, make it go faster

# abs() is not invertible, can replace with minmax scaling
S = numpy.abs(librosa.stft(y))

transformer = sklearn.decomposition.NMF(n_components=32)
W, H = librosa.decompose.decompose(S, transformer=transformer)
S_recomposed = W.dot(H)
print(numpy.sum(numpy.abs(S - S_recomposed)))

Note that the recomposition will never be perfect. But it should get better as n_components increases.

Jon Nordby
  • 5,494
  • 1
  • 21
  • 50
  • There's also a `numpy.isclose()`, which you can use instead of `numpy.sum(numpy.abs(new_array - old_array)) < some_value_that_is_possibly_scaled_with_array_size` when you want to check that two arrays are nearly equivalent - You'd use it like `numpy.all(numpy.isclose(new_array, old_array))`. (I also only learned about its existence earlier this week, so I'm eager to "spread the gospel", so to speak :) – Aleksi Torhamo Oct 06 '18 at 20:53
  • Yes, `numpy.isclose()` is super nice. But in this case I fear the result is not really close (numerically)! Got over 10k on that example. PS: `numpy.testing.assert_almost_equal(a, b)` is also great – Jon Nordby Oct 06 '18 at 21:03
  • Ooh! `assert_almost_equal()` is super nice! I was going to remark that I just wished it supported specifying both relative and absolute tolerances, like `isclose()`, but its documentation pointed to `numpy.testing.assert_allclose()`, which does! – Aleksi Torhamo Oct 07 '18 at 01:29