tags:

views:

209

answers:

3

Guys, Im trying to engineer in python a way of transforming a list of integer values between 0-255 into representative equivalent tones from 1500-2200Hz. Timing information (at 1200Hz) is given by the (-1),(-2) and (-3) values. I have created a function that generates a .wav file and then call this function with the parameters of each tone. I need to create a 'stream' either by concatenating lots of individual tones into one output file or creating some way of running through the entire list and creating a separate file. Or by some other crazy function I don't know of.... The timing information will vary in duration but the information bits (0-255) will all be fixed length.

A sample of the list is shown below:

[-2, 3, 5, 7, 7, 7, 16, 9, 10, 21, 16, -1, 19, 13, 8, 8, 0, 5, 9, 21, 19, 11, -1, 11, 16, 19, 5, 21, 34, 39, 46, 58, 50, -1, 35, 46, 17, 28, 23, 19, 8, 2, 13, 12, -1, 9, 6, 8, 11, 2, 3, 2, 13, 14, 42, -1, 35, 41, 46, 55, 73, 69, 56, 47, 45, 26, -1, -3]

The current solution I'm thinking of involves opening the file, checking the next value in the list using an 'if' statement to check whether the bit is timing (-ve) and if not: run an algorithm to see what freq needs to be generated and add the tone to the output file. Continue until -3 or end of list.

Can anyone guide on how this complete output file might be created or any suggestions... I'm new to programming so please be gentle. Thanks in advance

+2  A: 

Looks like you're trying to reinvent the wheel, be careful... If you want to generate music from arrays then you can have a look at pyaudiere, a simple wrapper upon the audiere library. See the docs for how to open an array but it looks should like this :

import audiere
d = audiere.open_device()
s = d.open_array(buff,fs)
s.play()

the documentation for this call is:

open_array(buffer, fs) :

Opens a sound buffer for playback, and returns an OutputStream object for it. The buffer should be a NumPy array of Float32's with one or two columns for mono of stereo playback. The second parameter is the sampling frequency. Values outside the range +-1 will be clipped.

attwad
A: 

All you need to do is just append the new data on the end of your wav file. So if you haven't closed your file, just keep writing to it, or if you have, reopen it in append mode (w = open(myfile, 'ba')) and write the new data.

For this to sound reasonable without clicks and such, the trick will be to make the waveform continuous from one frequency to the next. Assuming that you're using sine waves of the same amplitude, you need to start each sine wave with the same phase that you ended the previous. You can do this either by playing with the length of the waveform to make sure you always end at, say, zero phase and then always start at zero phase, or by explicitly including the phase in the sine wave.

tom10
A: 

I'm not sure I understand exactly what you're asking, but I'll try to answer.

I wouldn't mess around with the low-level WAV format if I didn't have to. Just use Audiolab for this.

  1. Initialize an empty song NumPy 1-D array
  2. Open your file of numbers
  3. Use the if statement as you said, to detect if it's a negative or positive number
  4. Generate a "snippet" of tone according to your formula (which I don't really understand from the description).
    1. First generate a timebase with something like t = linspace(0,1,num=48000)
    2. Then generate the tone with something like a = sin(2*pi*f*t)
  5. Concatenate the snippet onto the rest of the array with something like song = concatenate((song,a))
  6. Loop through the file to create and concatenate each snippet
  7. Write to a WAV file using something like wavwrite(song, 'filename.wav', fs, enc)

Did you think up this format of tones and timing yourself or is it something created by others?

endolith