1
votes

I'm creating WAV file and write list of specific notes frequency separate by silence note with const duration in 44100 sample_rate for example 440 Hz, silence, 351 Hz, silence etc. now i want to read from the WAV file and get the exact frequency list. how can i do that? thanks!

This is my note to WAV code:

# !/usr/bin/python
# based on : www.daniweb.com/code/snippet263775.html
import math
import wave
import struct
import txtToNote

# Audio will contain a long list of samples (i.e. floating point numbers describing the
# waveform).  If you were working with a very long sound you'd want to stream this to
# disk instead of buffering it all in memory list this.  But most sounds will fit in
# memory.
import wavToNote

audio = []
sample_rate = 44100.0


def append_silence(duration_milliseconds=500):
    """
    Adding silence is easy - we add zeros to the end of our array
    """
    num_samples = duration_milliseconds * (sample_rate / 1000.0)

    for x in range(int(num_samples)):
        audio.append(0.0)

    return


def append_sinewave(freq=440.0, duration_milliseconds=1000, volume=1.0):
    """
    The sine wave generated here is the standard beep.  If you want something
    more aggressive you could try a square or saw tooth waveform.   Though there
    are some rather complicated issues with making high quality square and
    sawtooth waves... which we won't address here :)
    """

    global audio  # using global variables isn't cool.

    num_samples = duration_milliseconds * (sample_rate / 1000.0)

    print("audio:")
    for x in range(int(num_samples)):
        audio.append(volume * math.sin(2 * math.pi * freq * (x / sample_rate)))

    return


def revers_audio():
    print("hi")




def save_wav(file_name):
    # Open up a wav file
    wav_file = wave.open(file_name, "w")

    # wav params
    nchannels = 1

    sampwidth = 2

    # 44100 is the industry standard sample rate - CD quality.  If you need to
    # save on file size you can adjust it downwards. The stanard for low quality
    # is 8000 or 8kHz.
    nframes = len(audio)
    comptype = "NONE"
    compname = "not compressed"
    wav_file.setparams((nchannels, sampwidth, sample_rate, nframes, comptype, compname))

    # WAV files here are using short, 16 bit, signed integers for the
    # sample size.  So we multiply the floating point data we have by 32767, the
    # maximum value for a short integer.  NOTE: It is theortically possible to
    # use the floating point -1.0 to 1.0 data directly in a WAV file but not
    # obvious how to do that using the wave module in python.
    for sample in audio:
        wav_file.writeframes(struct.pack('h', int(sample * 32767.0)))

    wav_file.close()

    return

# txt_to_note is my function that return frequency (float) for each latter in the string
# (the letters are note chords!)
# for simplicity ['a' = 220, 'b' = 467, 'c' = 351, 'd' = 367]
for i in txtToNote.txt_to_note("abcda"):
    append_sinewave(freq=i)
    append_silence()

save_wav("output.wav")

if __name__ == '__main__':
    pass
1

1 Answers

1
votes

You'd read the signal from the file, window it into suitably long chunks depending on your desired temporal resolution, run FFT on each chunk to get frequency data and find the peaks.

You can find windowing and FFT in the Scipy library.