Skip to content

Instantly share code, notes, and snippets.

@ohsqueezy
Last active March 14, 2022 09:46
Show Gist options
  • Save ohsqueezy/6540433 to your computer and use it in GitHub Desktop.
Save ohsqueezy/6540433 to your computer and use it in GitHub Desktop.
Play a 440 Hz tone in Pygame
# Generate a 440 Hz square waveform in Pygame by building an array of samples and play
# it for 5 seconds. Change the hard-coded 440 to another value to generate a different
# pitch.
#
# Run with the following command:
# python pygame-play-tone.py
from array import array
from time import sleep
import pygame
from pygame.mixer import Sound, get_init, pre_init
class Note(Sound):
def __init__(self, frequency, volume=.1):
self.frequency = frequency
Sound.__init__(self, self.build_samples())
self.set_volume(volume)
def build_samples(self):
period = int(round(get_init()[0] / self.frequency))
samples = array("h", [0] * period)
amplitude = 2 ** (abs(get_init()[1]) - 1) - 1
for time in range(period):
if time < period / 2:
samples[time] = amplitude
else:
samples[time] = -amplitude
return samples
if __name__ == "__main__":
pre_init(44100, -16, 1, 1024)
pygame.init()
Note(440).play(-1)
sleep(5)
@solarmist
Copy link

Current pygame needs to change line 28 to
Sound.init(self, buffer=self.build_samples())

@revolunet
Copy link

you meant line 18

@jolespin
Copy link

i can't get this to work :/
File "synesthesia.py", line 24, in init
Sound.init(self, buffer=self.build_samples())
AttributeError: type object 'Sound' has no attribute 'init'

@talespadua
Copy link

to work, change:
Sound.init(self, buffer=self.build_samples())
to:
pygame.mixer.Sound.init(self, buffer=self.build_samples())

@GeorgeInNC
Copy link

I've tried all the variations proposed and none of them have worked for me. I'm on a Raspberry Pi 3 using Python 3.4.2.

@danellisuk
Copy link

If you are using python3, change xrange to range. This is all that I needed to change for this to work on my Raspberry Pi 3.

@JetStarBlues
Copy link

As per this answer on StackOverflow, if the snippet doesn't work and you are running it on Windows, the problem might be the need for a screen on Windows. Creating a screen as follows before the call to Note() resolved it for me,

pygame.display.set_mode( ( screen_width, screen_height ) )

@Sitin
Copy link

Sitin commented Oct 2, 2017

This snippet won't produce a sine wave but rather a square wave (which sounds much sharper). For the sine wave replace build_samples with something like:

def build_samples(self):
    sample_rate = pygame.mixer.get_init()[0]
    period = int(round(sample_rate / self.frequency))
    amplitude = 2 ** (abs(pygame.mixer.get_init()[1]) - 1) - 1

    def frame_value(i):
        return amplitude * numpy.sin(2.0 * numpy.pi * frequency * i / sample_rate)

    return numpy.array([frame_value(x) for x in range(0, period)]).astype(numpy.int16)

Or use a simpler approach without inheriting Sound class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment