0

I'm using sndarray from pygame to play with basic sound synthesis. The problem is Whatever I do, I have an awful distortion on the generated sound.

In the code I'll provide at the end of the question, you'll see a bunch of code coming from here and there. Actually, the main stuff comes from a MIT's source I found on the interweb which is using Numeric to do mathematic stuff and handling arrays, and since I can't install it for now, I decided to use Numpy for this.

First, I thought the problem was coming from the Int format of my arrays, but if I cast the values to numpy.int16, I don't have sound anymore.

Plus, I can't find anything on google about that kind of behavior from pygame / sndarray.

Any idea ?

Thanks !

Code :

global_sample_rate = 44100

def sine_array_onecycle(hz, peak):
    length = global_sample_rate / float(hz)
    omega = numpy.pi * 2 / length
    xvalues = numpy.arange(int(length)) * omega 
    return (peak * numpy.sin(xvalues))

def zipstereo(f):
    return numpy.array(zip (f , f))

def make_sound(arr, n_samples = global_sample_rate):
    return pygame.sndarray.make_sound( zipstereo( numpy.resize(numpy.array(arr), (n_samples,)) ) )

def sine(hz, peak):
    snd = make_sound(sine_array_onecycle(hz, peak), global_sample_rate)
    return snd

=> 'hope I didn't make any lame mistake, I'm pretty new in the world of python

Hezad
  • 146
  • 7
  • Have you tried saving the sound data in a standard format (e.g. WAV) and inspecting it in an audio editor to see if it looks like you expect? – Karl Knechtel Oct 26 '11 at 10:46
  • That's actually a very good idea. I think I can export my audio arrays to audio files so I can check that. – Hezad Oct 26 '11 at 12:26
  • Comments for the function http://pygame.org/docs/ref/sndarray.html#pygame.sndarray.make_sound indicate poor quality issue, and code suggests that you are missing some steps... – Benjamin Nov 08 '11 at 03:04
  • Hum actually even if it does sound better, the sound generated by the code on that page (I already tried that ;)) still sounds more like a saw / triangular signal to my ears (high or low frequencies) but it should sound like a sine, nope ? – Hezad Nov 08 '11 at 17:12

1 Answers1

2

Presuming you have some initialization code like

pygame.mixer.pre_init(44100, -16, 2) # 44.1kHz, 16-bit signed, stereo

sndarray expects you to be passing it 16-bit integer arrays, not float arrays.

Your "peak" value needs to make sense given the 16-bit integer representation. So, if your float array has values in the range -1.0 to +1.0, then you need to multiply by 2**15 to get it scaled appropriately.

To be clear, you may want a conversion like:

numpy.int16(float_array*(2**15))

My best guess of the situation is that you had a float array with a low peak value like 1.0, so when converting it to int16 most everything was getting converted to 0 or +/-1, which you wouldn't be able to hear. When passing the float array, you were probably just getting random bits (when interpreted as 16 bit integers) so then it sounded like harsh noise (I stumbled through this phase on my way to getting this working).

Andrew Rosenfeld
  • 1,711
  • 1
  • 12
  • 9