Robin Andrews
Robin Andrews

Reputation: 3804

Python 2 to Python 3 Struct Pack Issue

I'm trying to get the following code to work in Python 3. It is fine in Python 2. I have changed the xranges to range, but there is a problem with this line: data = ''.join(struct.pack('f', samp) for samp in tone):

sequence item 0: expected str instance, bytes found.

I found this answer but couldn't work out how to apply it to my situation. Any help much appreciated.

import math
import struct
import pyaudio

def play_tone(frequency, amplitude, duration, fs, stream):
    N = int(fs / frequency)
    T = int(frequency * duration)  # repeat for T cycles
    dt = 1.0 / fs
    # 1 cycle
    tone = (amplitude * math.sin(2 * math.pi * frequency * n * dt)
            for n in xrange(N))
    # todo: get the format from the stream; this assumes Float32
    data = ''.join(struct.pack('f', samp) for samp in tone)
    for n in xrange(T):
        stream.write(data)

fs = 48000
p = pyaudio.PyAudio()
stream = p.open(
    format=pyaudio.paFloat32,
    channels=1,
    rate=fs,
    output=True)

# play the C major scale
scale = [130.8, 146.8, 164.8, 174.6, 195.0, 220.0, 246.9, 261.6]
for tone in scale:
    play_tone(tone, 0.5, 0.75, fs, stream)

# up an octave
for tone in scale[1:]:
    play_tone(2*tone, 0.5, 0.75, fs, stream)

stream.close()
p.terminate()

Upvotes: 3

Views: 1870

Answers (1)

Blckknght
Blckknght

Reputation: 104842

The issue is that the empty string you're joining on is in fact a str instance (a Unicode string), but the values you're joining together (that you get from struct.pack) are bytes instances. Python 3 doesn't let you mix the different string types together like that.

Change the '' to b'' and it should work: data = b''.join(struct.pack('f', samp) for samp in tone)

Upvotes: 3

Related Questions