instead of depending on data = array('h') .. write samples 1 by 1 to w = wave.open("wav.wav", "w")
Peter Otten
__peter__ at web.de
Wed Jul 29 04:21:05 EDT 2009
'2+ wrote:
> it says
> Wave_write.writeframes(data)
> will that mean
> "from array import array"
> is a must?
>
> this does the job:
>
> import oil
> import wave
> from array import array
>
> a = oil.Sa()
>
> w = wave.open("current.wav", "w")
> w.setnchannels(2)
> w.setsampwidth(2)
> w.setframerate(44100)
>
> data = array('h')
>
> for gas in range(44100 * 5):
> a.breath()
> r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
> l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
> data.append(r)
> data.append(l)
>
> w.writeframes(data.tostring())
> w.close()
>
> don't like array becoming so huge so tested this and it was also okay:
>
> for gas in range(44100 * 5):
> a.breath()
> data = array('h')
> r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
> l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
> data.append(r)
> data.append(l)
> w.writeframes(data.tostring())
>
> but without array .. it becomes 15secs(3 times longer than was
> intended to be) of wav file:
>
> for gas in range(44100 * 5):
> a.breath()
> r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
> l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
> w.writeframes(hex(r))
> w.writeframes(hex(l))
Doesn't it sound strange, too? You are writing bogus bytes to the file.
Compare:
>>> import array
>>> array.array("h", [42]).tostring()
'*\x00'
>>> hex(42)
'0x2a'
Not only do they differ in length, the contents are different, too. If
you're unfamiliar with string escape codes, here's a way to see the bytes:
>>> map(ord, array.array("h", [42]).tostring())
[42, 0]
>>> map(ord, hex(42))
[48, 120, 50, 97]
> should i just be happy with depennding on using array?
> or is there a solution to make the last one work properly?
There is a way to make the last one work: use struct.pack("h", r) instead of
hex(r). I'm of course assuming that the first version does give you the
desired result. You should not continue before you have verified that.
I still recommend array for performance reasons. If memory usage is an issue
you can adopt a hybrid approach:
# untested
from itertools import islice
from array import array
def gen_data():
for gas in xrange(44100 * 5): # range --> xrange
a.breath()
r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
yield r
yield l
data = gen_data()
N = 2**20
while True:
chunk = array('h')
chunk.extend(islice(data, N))
if not chunk:
break
w.writeframes(chunk.tostring())
This will limit the array size to 4N bytes.
Peter
More information about the Python-list
mailing list