Skip to content

Instantly share code, notes, and snippets.

@rtanglao
Created July 4, 2010 05:45
Show Gist options
  • Select an option

  • Save rtanglao/463187 to your computer and use it in GitHub Desktop.

Select an option

Save rtanglao/463187 to your computer and use it in GitHub Desktop.
play gamelan sounds with your N900
#----------------------------------------------------------------------------------
#
# This file is part of PygSoundTestTest.
# PygSoundTestTest should generate and play sound data . . .
#
# PygSoundTestTest Copyright (C) 2009, 2010 by Matthew N. Brown
# N900 / Maemo Modifications (change radians to math.radians and use Numeric instead of NumP) by Roland Tanglao
# PygSoundTestTest is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PygSoundTestTest is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PygSoundTestTest. If not, see <http://www.gnu.org/licenses/>.
#
#----------------------------------------------------------------------------------
#
# PygSoundTestTest version 3?
#
# Now you can play gamelan-sounding music!
#
#
# requirements to run PygSoundTestTest:
# (python 2.5 or higher)?
# and: (pygame 2.8.0 or pygame 2.8.1)?
# and: (numpy)?
#
#
#
#
# Press Esc to close the program.
#
#
# Not sure if this is a glitch, but it might be usefull for you to know that:
#
# pygame.sndarray.make_sound() sometimes returns pygame.channel()?
#
# (I'm not sure why, but, on my computer, "every-once-and-a-while", this program will close and give one of these errors:
#
# This one: Fatal Python error: (pygame parachute) Segmentation Fault This application has requested the runtime to terminate in an unusual way. Please contact the application's support team for more information.
#
# Or this one: TypeError: argument 1 must be pygame.mixer.Sound, not Channel
#
# Or this one: Runtime Error! This application has requested the runtime to terminate in an unusual way. Please contact the application's support team for more information.
#
# I've been trying to get around these glitches for a while . . . So far I haven't been able to . . .
# It seems as though those glitches are unique to Windows.
#
#
#
#
#
#
#
# Oh, and please be carefull while experimenting with "sound generating code";
#
# It is very easy to accidentally hurt your ears by increasing the volume or pitch too much! (Yikes! I've done that many times! :( )
# Also I suggest taking frequent breaks while programming. This has helped me a lot.
#
#
#
#
#
#
#
# Here's the code:
#
## initialization (This function should only be executed once):
def HE_HE_init():
global screen
global screen_x_size
global screen_y_size
global channel_max
if sys.platform == 'win32' or sys.platform == 'win64':
os.environ['SDL_VIDEO_CENTERED'] = '1'
# init the pygame.mixer according to the pygame version number:
versiony_numbery = pygame.version.vernum
numby = int(str(versiony_numbery[0]) + str(versiony_numbery[1]) + str(versiony_numbery[2]))
print numby
if numby >= 181: pygame.mixer.init(44100, -16, 1)
else: pygame.mixer.init(22050, -16, 2)
pygame.init()
random.seed()
channel_max = 5
pygame.mixer.set_num_channels(channel_max)
screen_x_size = 800
screen_y_size = 480
screen = pygame.display.set_mode((screen_x_size, screen_y_size))
pygame.mouse.set_visible(1)
pygame.display.set_caption('PygSoundTestTest copyright 2009, 2010 by Matthew N. Brown')
pygame.display.flip()
## This function contains the "main loop":
def Lets_ROLL():
# A tuple containing some frequencies/Hz/Cycles-per-second:
noteyish = (130.059, 149.226, 171.119, 197.931, 225.142, 260.119, 298.452, 342.238, 395.863, 450.285, 520.238, 596.905, 684.477, 791.726, 900.570, 520.238*2.0, 596.905*2.0, 684.477*2.0, 791.726*2.0, 900.570*2.0) # A "gamelan slendro" tuning.
###noteyish = (440, 493.883, 261.626, 293.665, 329.628, 349.228, 391.995,
### 440*2.0, 493.883*2.0, 261.626*2.0, 293.665*2.0, 329.628*2.0, 349.228*2.0, 391.995*2.0,
### 440/2.0, 493.883/2.0, 261.626/2.0, 293.665/2.0, 329.628/2.0, 349.228/2.0, 391.995/2.0 # Some "white-keys" of the Western "12-tone-equal-temperament"? (ABCDEFGs)
### )
# A little something that might be good to know:
# To get a frequencey/note exactly one octave higher than another frequencey/note --> frequencey2 = frequencey1 * 2.0
# To get a frequencey/note exactly one octave LOWER than another frequencey/note --> frequencey2 = frequencey1 / 2.0
pygame_noteyish_sound = []
for n in range(0, len(noteyish)):
screen.fill((0, 0, 0))
key = pygame.key.get_pressed()
if key[K_ESCAPE]: END()
for event in pygame.event.get():
if event.type == QUIT: END()
pygame_noteyish_sound += [generate_numpy_sound_data__draw_numpy_sound_data__and__return_pygame_sound__hehe( noteyish[n] )]
print '_____________________________________'
print 'Hold down number keys to play sounds?'
print '_____________________________________'
t = time.time()
#hehe1_t = time.time() + 0.1
#hehe2_t = time.time() + 0.3
#hehe3_t = time.time() + 0.7
while True: # <-- "Main loop"
# Keep program from running/executing "too fast":
while t > time.time(): pass
t = time.time() + 0.01
screen.fill((0, 0, 0))
# Close the window/program if: [Esc is pressed] or: [The X button is pressed]
key = pygame.key.get_pressed()
if key[K_ESCAPE]: END()
for event in pygame.event.get():
if event.type == QUIT: END()
if event.type == KEYDOWN:
##a,s,d,f,g,h,j,k,l,.
if event.key == 97: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[0], 0)
if event.key == 115: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[1], 0)
if event.key == 100: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[2], 0)
if event.key == 102: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[3], 0)
if event.key == 103: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[4], 0)
if event.key == 104: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[5], 0)
if event.key == 106: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[6], 0)
if event.key == 107: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[7], 0)
if event.key == 108: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[8], 0)
if event.key == 46: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[9], 0)
##z,x,c,v,b,n,m, space bar,q,w
if event.key == 122: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[10], 0)
if event.key == 120: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[11], 0)
if event.key == 99: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[12], 0)
if event.key == 118: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[13], 0)
if event.key == 98: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[14], 0)
if event.key == 32: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[15], 0)
if event.key == 109: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[16], 0)
if event.key == 32: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[17], 0)
if event.key == 113: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[18], 0)
if event.key == 119: pygame.mixer.find_channel(True).play(pygame_noteyish_sound[19], 0)
#if hehe1_t < time.time():
# pygame.mixer.find_channel(True).play(pygame_noteyish_sound[ int(random.random() * (len(noteyish) - 1) ) ], 0)
# hehe1_t = time.time() + 8.0
#if hehe2_t < time.time():
# pygame.mixer.find_channel(True).play(pygame_noteyish_sound[ int(random.random() * (len(noteyish) - 1) ) ], 0)
# hehe2_t = time.time() + 4.0
#if hehe3_t < time.time():
# pygame.mixer.find_channel(True).play(pygame_noteyish_sound[ int(random.random() * (len(noteyish) - 1) ) ], 0)
# hehe3_t = time.time() + 2.0
#generate_numpy_sound_data__draw_numpy_sound_data__and__return_pygame_sound__hehe( noteyish[int(random.random() * (len(noteyish) - 1) )] )
pygame.display.flip()
def generate_numpy_sound_data__draw_numpy_sound_data__and__return_pygame_sound__hehe(cicles_per_every_second):
##### generate/create and display/draw numpy_sound_data: #####
total_duration_in_seconds = 1.0
samples_per_second = 22050
total_amount_of_samples = total_duration_in_seconds * samples_per_second
###cicles_per_every_second = 440.0
numpy_sound_data = array([0] * int(total_amount_of_samples)) ## A variable called "numpy_sound_data" is created. (full of zeros right now) (It's a "numpy array" type variable) (A "numpy array" is kind of like a Python "list", but can be larger and faster to "index". (I think))
wavey_gurgy = 0.0
frequencey_wavery = 0.0
frequencey_wavery_speedy = cicles_per_every_second * 0.0000005 + 0.05
frequencey_wavery_magnitudey = cicles_per_every_second * 0.002 + 10.0
volumey_wavery = 0.0
volumey_wavery_speedy = cicles_per_every_second * 0.00000005 + 0.003
volumey_wavery_magnitudey = cicles_per_every_second * 0.1 + 20.0
#volumey2_wavery = 0.0
#volumey2_wavery_speedy = cicles_per_every_second / 2000000.0
#volumey2_wavery_magnitudey = cicles_per_every_second * 2.0 + 100.0
pinch_type = 2
do_frequencey_wavery = True
do_volume_wavery = True
# variables begining with "specialy" are for "pinching" the sound data at both ends. (This is to give the sounds a soft sound)
specialy = len(numpy_sound_data) - 1
specialy__amount_of_samples_to_pinch_at_left_end = 200.0
specialy__amount_of_samples_to_pinch_at_right_end = 4000.0
specialyy2 = specialy - specialy__amount_of_samples_to_pinch_at_right_end
specialyy3 = 0 + specialy__amount_of_samples_to_pinch_at_left_end
if specialy > 2000: specialy -= 2000
# setup some variables for drawing/displaying numpy_sound_data:
x = 0
y = 200
x_dividey = 20
y_dividey = 500
y_addy = 200
x2 = 0
y2 = 400
x2_dividey = 2
y2_addy_addy = 200
for n in range(0, len(numpy_sound_data)): # Yes, this "for-loop" should change each individual "sample" (One by one) (Cool, eh?)
if do_frequencey_wavery:
frequencey_wavery += frequencey_wavery_speedy
hehehe_frequencey_addy = math.sin( frequencey_wavery * math.radians(360) ) * frequencey_wavery_magnitudey
wavey_gurgy += ( float(cicles_per_every_second + hehehe_frequencey_addy) / float(samples_per_second) )
current_frequencey = math.sin( wavey_gurgy * math.radians(360) )
else:
wavey_gurgy += ( float(cicles_per_every_second) / float(samples_per_second) )
current_frequencey = math.sin( wavey_gurgy * math.radians(360) )
if do_volume_wavery:
volumey_wavery += volumey_wavery_speedy
hehehe_volumey_addy = math.sin( volumey_wavery * math.radians(360) ) * volumey_wavery_magnitudey
#volumey2_wavery += volumey2_wavery_speedy
#hehehe_volumey2_addy = math.sin( volumey2_wavery * radians(360) ) * volumey2_wavery_magnitudey
#current_volume = (10000.0 + hehehe_volumey_addy + hehehe_volumey2_addy)
current_volume = (10000.0 + hehehe_volumey_addy)
else:
current_volume = 10000.0
numpy_sound_data[n] = int( current_frequencey * current_volume )
# This "pinches" the ends of the "numpy_sound_data":
if pinch_type == 1:
if n >= specialyy2:
numpy_sound_data[n] *= (1.0 - (n - specialyy2) / specialy__amount_of_samples_to_pinch_at_right_end)
if n <= specialyy3:
numpy_sound_data[n] *= (n / specialy__amount_of_samples_to_pinch_at_left_end)
elif pinch_type == 2:
if n >= specialyy2:
gr_a_number_between_0_and_1 = (1.0 - (n - specialyy2) / specialy__amount_of_samples_to_pinch_at_right_end)
numpy_sound_data[n] *= math.sin( gr_a_number_between_0_and_1 * math.radians(360) * 0.25 )
if n <= specialyy3:
gr_a_number_between_0_and_1 = (n / specialy__amount_of_samples_to_pinch_at_left_end)
numpy_sound_data[n] *= math.sin( gr_a_number_between_0_and_1 * math.radians(360) * 0.25 )
# Draw/plot two stretched versions of the "numpy_sound_data":
xa = x
ya = y
x = n / x_dividey
y = numpy_sound_data[n] / y_dividey + y_addy
xa2 = x2
ya2 = y2
x2 = n / x2_dividey
y2 = y + y2_addy_addy
pygame.draw.line(screen, (100, 200, 200), (x, y), (xa, ya))
pygame.draw.line(screen, (100, 200, 200), (x2, y2), (xa2, ya2))
pygame.display.flip()
###### convert "numpy_sound_data" to pygame.mixer.Sound and play it: #######
sound_thing = numpy_sound__converted_to_a__pygame_sound( numpy_sound_data )
## print type(sound_thing)
pygame.mixer.find_channel(True).play(sound_thing, 0)
return sound_thing
def numpy_sound__converted_to_a__pygame_sound(numpy_sound_data):
return pygame.sndarray.make_sound(numpy_sound_data)
#pygame_sound = pygame.sndarray.make_sound(numpy_sound_data)
#try:
# channely = pygame.mixer.find_channel(True)
# channely.set_volume(0)
# channely.play(pygame_sound, 0)
# channely.stop()
# channely.set_volume(1)
# return pygame_sound
#except Exception, e:
# print "Awkward . . . There was an error? "
# return None
## A function to end/close the program:
def END():
print ''
print 'Program ended?'
print "###############################################################################"
print "###############################################################################"
print ''
pygame.quit()
raise SystemExit, ''
## "import" some modules from Python:
import os
import sys
import math
import random
import time
#import gc
#import copy as pythoncopy
#import string
#import struct
#from time import strftime, localtime
#import wave
print ""
print "###############################################################################"
print "###############################################################################"
print "Program started? "
print ""
print ""
print ""
print ""
print ""
## "import" some modules other than Python's builtin modules:
try:
import pygame
from pygame.locals import *
if not pygame.font: print '?? "pygame.font" not "found" ??'
if not pygame.mixer: print '?? "pygame.mixer" not "found" ??'
from pygame import scrap
except: print '"pygame" not "found"???'
#try:
# import numpy; from numpy import *
#except: print '"numpy" not "found"??? (Oh well! Who cares!)'
#try:
# import numarray; from numarray import *
#except: print '"numarray" not "found"??? (Oh well! Who cares!)'
#try:
# import Numeric; from Numeric import *
#except: print '"numeric" not "found"??? (Oh well! Who cares!)'
from Numeric import *
# After all "imports" are "imported" and after all "functions" have been "defined",
# execute "HE_HE_init()" once. After that, execute "Lets_ROLL()" ("Lets_ROLL()" contains the "main loop").
HE_HE_init()
Lets_ROLL()
END()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment