简体   繁体   中英

Writing bytes to wave file?

I have some data in Python which I want to output to a WAV file. Right now I'm generating all of the samples as shorts and putting them into a buffer. Then whenever that buffer hits a certain length, I pack the data and send it to writeframes (compromising between writing every sample, which is slow, and holding the whole thing in memory before writing, which is expensive).

But it always throws a TypeError.

output = wave.open(fname, 'wb')
output.setparams((channels, sample_width, sample_rate, 0, 'NONE', 'not compressed'))
# ...generate the data, write to the buffer, then if the buffer is full...
cooked = []
for (ldata, rdata) in rawdata:
    cooked.append(struct.pack('<hh',ldata,rdata)) # Pack it as two signed shorts, little endian
output.writeframes(bytes.join(cooked)) # Write to the wave file

I've also tried ''.join(cooked) , bytes(cooked) , and making cooked a bytearray from the start, but none of these seem to work.

As above

output.writeframes(bytes.join(cooked)) # Write to the wave file
TypeError: descriptor 'join' requires a 'bytes' object but received a 'list'

Using bytes()

output.writeframes(bytes(cooked)) # Write to the wave file
TypeError: 'bytes' object cannot be interpreted as an integer

Making cooked a bytearray

cooked.append(struct.pack('<hh',ldata,rdata)) # Pack it as two signed shorts, little endian
TypeError: an integer is required

Sending cooked in directly

TypeError: memoryview: list object does not have the buffer interface

Using ''.join()

output.writeframes(''.join(cooked)) # Write to the wave file
TypeError: sequence item 0: expected str instance, bytes found

What is the proper way to do this? I can't figure out what exactly Python wants.

EDIT: Using Python 3.4.1 if that affects anything.

You need to do this:

output.writeframes(b''.join(cooked))

The first argument to a method is self . If you call the method normally, this argument is passed automatically. If, however, you call it via Class.method() , you have to pass it manually. Since you passed a list instead of a bytes object as your first argument, you got the first TypeError.

For the sake of completeness, here are the remaining errors:

output.writeframes(bytes(cooked)) # Write to the wave file
TypeError: 'bytes' object cannot be interpreted as an integer

bytes() accepts a sequence of integers; moreover they are one byte at a time. You would need to use bitwise operations instead of struct.pack() (eg cooked.extend((ldata & 0xFF, ldata >> 8, rdata & 0xFF, rdata >> 8)) for little-endian 16-bit integers, assuming nothing is bigger than 0xFFFF and not accounting for negative numbers).

cooked.append(struct.pack('<hh',ldata,rdata)) # Pack it as two signed shorts, little endian
TypeError: an integer is required

Again, bytearray.append() accepts an integer.

output.writeframes(cooked)
TypeError: memoryview: list object does not have the buffer interface

A list is not a bytes-like object, so it is not acceptable to writeframes() .

output.writeframes(''.join(cooked)) # Write to the wave file
TypeError: sequence item 0: expected str instance, bytes found

You can't mix text and binary strings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM