How can I reverse a scipy.signal.spectrogram to audio with Python? - python

I have:
import librosa
from scipy import signal
import scipy.io.wavfile as sf
samples, sample_rate = sf.read(args.file)
nperseg = int(sample_rate * 0.001 * 20)
frequencies, times, spectrogram = signal.spectrogram(samples,
sample_rate,
nperseg=nperseg,
window=signal.hann(nperseg))
audio_signal = librosa.griffinlim(spectrogram)
print(audio_signal, audio_signal.shape)
sf.write('test.wav', audio_signal, sample_rate)
However, this produces a (near) empty sound file.

As #DrSpill mentioned, scipy.io.wav.read and scipy.io.wav.write orders were wrong and also the import from librosa was not correct. This should do it:
import librosa
import numpy as np
import scipy.signal
import scipy.io.wavfile
# read file
file = "temp/processed_file.wav"
fs, sig = scipy.io.wavfile.read(file)
nperseg = int(fs * 0.001 * 20)
# process
frequencies, times, spectrogram = scipy.signal.spectrogram(sig,
fs,
nperseg=nperseg,
window=scipy.signal.hann(nperseg))
audio_signal = librosa.core.spectrum.griffinlim(spectrogram)
print(audio_signal, audio_signal.shape)
# write output
scipy.io.wavfile.write('test.wav', fs, np.array(audio_signal, dtype=np.int16))
Remark:
The resulting file had an accelerated tempo when I heard it, I think this is due to your processing but with some tweaking it should work.
A good alternative, would be to only use librosa, like this:
import librosa
import numpy as np
# read file
file = "temp/processed_file.wav"
sig, fs = librosa.core.load(file, sr=8000)
# process
abs_spectrogram = np.abs(librosa.core.spectrum.stft(sig))
audio_signal = librosa.core.spectrum.griffinlim(abs_spectrogram)
print(audio_signal, audio_signal.shape)
# write output
librosa.output.write_wav('test2.wav', audio_signal, fs)

librosa.output was removed. It is no longer providing its deprecated output module. Instead try soundfile.write:
import numpy as np
import soundfile as sf
sf.write('stereo_file.wav', np.random.randn(10, 2), 44100, 'PCM_24')
#Per your code you could try:
sf.write('test.wav', audio_signal, sample_rate, 'PCM_24')

Related

how to call an object

I am trying to execute the following code but it is giving me an error
File "/home/utente/Desktop/python/untitled3.py", line 29, in <module>
bits = randn(Nbits,1) > 0
TypeError: 'module' object is not callable
import numpy as np
#import pandas as pd
import matplotlib.pyplot as plt
#import matplotlib.lines as lines
import random as randn
from numpy import r_
from numpy import sin
from numpy import pi
fs = 44100 # sampling rate
baud = 300 # symbol rate
Nbits = 10 # number of bits
Ns = fs/baud
N = Nbits * Ns
f0 = 1800
# bits = randn(Nbits,1) > 0
np.random.seed(seed=1)
bits = randn(Nbits,1) > 0
M = np.tile(bits,(1,Ns))
t = r_[0.0:N]/fs
OOK = M.ravel()*sin(2*pi*f0*t)
fig = plt.figure(figsize = (16,4))
plt(t,OOK)
If you are trying to call the randn method, it is part of the random module.
Since you imported the random module as randn, the call should be randn.randn(Nbits, 1).
I would suggest usind randn directly from the numpy module, as np.random.randn(Nbits, 1)
Let's read the error. 'module' object is not callable in the code bits = randn(Nbits,1) > 0.
There is only one function call there, which is randn(). However, you imported it as import random as randn. This only gives an alias to the module 'random'. What you need to do is use a function from the module, like random.randint() (after importing the module 'random', without an alias).
From your code, I assume you are looking for numpy.random.randn. In that case, add this line to your import statements.
from numpy.random import randn
You're creating a namespace collision by importing the random module as randn which is the method you wish to call from that module. So you need to remove that assignment and reference the np.random.randn module explicitly (or add a from np.random import randn).
import numpy as np
#import pandas as pd
import matplotlib.pyplot as plt
#import matplotlib.lines as lines
import random as randn <- REMOVE THIS LINE
from numpy import r_
from numpy import sin
from numpy import pi
fs = 44100 # sampling rate
baud = 300 # symbol rate
Nbits = 10 # number of bits
Ns = fs/baud
N = Nbits * Ns
f0 = 1800
# bits = randn(Nbits,1) > 0
np.random.seed(seed=1)
bits = randn(Nbits,1) > 0 <- CHANGE THIS TO bits = np.random.randn(Nbits,1) > 0
M = np.tile(bits,(1,Ns))
t = r_[0.0:N]/fs
OOK = M.ravel()*sin(2*pi*f0*t)
fig = plt.figure(figsize = (16,4))
plt(t,OOK)

How to create multichannel .WAV file in Python?

The .WAV format looks like it should allow more than two channels (nChannels).
But unfortunately scipy.io.wavfile only writes 1 or 2.
I don't really want to manually write my own Python WAV-writer, but I can't find anything out there.
Is there any code out there that does the job?
It turns out the documentation for scipy.io.wavfile is incorrect.
Looking at the source code, I can clearly see that it accepts an arbitrary number of channels.
The following code works:
import numpy as np
from scipy.io import wavfile
fs = 48000
nsamps = fs * 10
A, Csharp, E, G = 440.0, 554.365, 660.0, 783.991
def sine(freqHz):
τ = 2 * np.pi
return np.sin(
np.linspace(0, τ * freqHz * nsamps / fs, nsamps, endpoint=False)
)
A7_chord = np.array( [ sine(A), sine(Csharp), sine(E), sine(G) ] ).T
wavfile.write("A7--4channel.wav", fs, A7_chord)

Writing WAV file using Python, Numpy array and WAVE module

I am trying to implement the Karplus-Strong algorithm.
All is looking fine when I play (through Jupyter Notebook using Audio(y, rate=Fs)) the collected numpy array (representing guitar accord).
Unfortunately, writing the numpy array: y, into wav file using WAVE module is incorrect (using the next python code):
noise_output = wave.open('k-s.wav', 'w')
noise_output.setparams((1, 4, Fs, 0, 'NONE', 'not compressed'))
for i in range(0, len(y)):
value = y[i]
packed_value = struct.pack('f', value)
noise_output.writeframes(packed_value)
noise_output.close()
Each element of y is
<type 'numpy.float64'>
How should I amend the writing loop in order write the WAV file correctly?
Some more information about the issue. Before writing to WAV, the first elements of the y array are:
[ 0.33659756 0.33659756 -0.43915295 -0.87036152 1.40708988 0.32123558
-0.6889402 1.9739982 -1.29587159 -0.12299964 2.18381762 0.82228042
0.24593503 -1.28067426 -0.67568838 -0.01843234 -1.830472 1.2729578
-0.56575346 0.55410736]
After writing the elements to the WAV file, close the WAV file and read it again, I got this for the first 20 elements of the collected array:
[ 1051481732 1051481732 -1092560728 -1084305405 1068768133 1050966269
-1087349149 1073523705 -1079648481 -1107564740 1074512811 1062371576
1048303204 -1079775966 -1087571478 -1130954901 -1075163928 1067642952
-1089415880 1057872379]
Here are code samples to write a (stereo) wave file using the wave standard library.
I included two examples: one using numpy, and one that doesn't require any dependencies.
Using a numpy array
Note that if your data is in a numpy array, no need for the struct library.
import wave
import numpy as np
samplerate = 44100
# A note on the left channel for 1 second.
t = np.linspace(0, 1, samplerate)
left_channel = 0.5 * np.sin(2 * np.pi * 440.0 * t)
# Noise on the right channel.
right_channel = np.random.random(size=samplerate)
# Put the channels together with shape (2, 44100).
audio = np.array([left_channel, right_channel]).T
# Convert to (little-endian) 16 bit integers.
audio = (audio * (2 ** 15 - 1)).astype("<h")
with wave.open("sound1.wav", "w") as f:
# 2 Channels.
f.setnchannels(2)
# 2 bytes per sample.
f.setsampwidth(2)
f.setframerate(samplerate)
f.writeframes(audio.tobytes())
Using a list
This is (almost) the same code but without using numpy. No external dependencies are required.
import math
import random
import struct
import wave
samplerate = 44100
left_channel = [
0.5 * math.sin(2 * math.pi * 440.0 * i / samplerate) for i in range(samplerate)
]
right_channel = [random.random() for _ in range(samplerate)]
with wave.open("sound2.wav", "w") as f:
f.setnchannels(2)
f.setsampwidth(2)
f.setframerate(samplerate)
for samples in zip(left_channel, right_channel):
for sample in samples:
sample = int(sample * (2 ** 15 - 1))
f.writeframes(struct.pack("<h", sample))
import scipy.io.wavfile
scipy.io.wavfile.write("karplus.wav", Fs, y)
Tada! AFAIK works with float64 and float32, and probably others. For stereo, shape must be (nb_samples, 2). See scipy.io.wavfile.write.
Read and write wave file to and from a file:
from scipy.io import wavfile
sampling_rate, data = wavfile.read(wpath)
wavfile.write('abc1.wav', sampling_rate, data)

How to remove the noise from wave file

I have a sound file, I apply a high frequency filter
import wave
import scipy.io.wavfile as wav
import numpy as np
import scipy as sp
origAudio = wave.open('3734.wav','r')
frameRate = origAudio.getframerate()
nChannels = origAudio.getnchannels()
sampWidth = origAudio.getsampwidth()
nbframe=origAudio.getnframes()
da = np.fromstring(origAudio.readframes(frameRate), dtype=np.int16)
left, right = da[0::2], da[1::2]
b, a = signal.butter(2, 0.03,btype='highpass', analog=False)
left = signal.filtfilt(b, a, left)
hann = np.hanning(len(left))
l,f=np.fft.rfft(left*hann), np.fft.rfft(right)
plt.xscale('log')
plt.xlabel('frequency [Hz]')
plt.ylabel('|Magnitude|')
plt.plot(np.abs(l))
I obtain
However I want to remove the noise from the signal , abtain only the peaks.Thanks

looking for reading audio wave values in python

I'm trying to read and manipulate audio file ,
how to read and manipulate the waves value of a wave file using python?
The SciPy libraries have great resources for this:
Writing and Reading:
import numpy as np
from scipy.io import wavfile
fs = 44.1e3
t = np.arange(0, 1.0, 1.0/fs)
f1 = 440
f2 = 600
x = 0.5*np.sin(2*np.pi*f1*t) + 0.5*np.sin(2*np.pi*f2*t)
fname = 'output.wav'
wavfile.write( fname, fs, x )
fs, data = wavfile.read( fname )
print fs, data[:10]
Documentation:
http://docs.scipy.org/doc/scipy-0.14.0/reference/io.html#module-scipy.io.wavfile
Reading: http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.io.wavfile.read.html#scipy.io.wavfile.read
Writing: http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.io.wavfile.write.html#scipy.io.wavfile.write
This question has been asked before: Reading *.wav files in Python

Categories

Resources