Created
July 4, 2010 05:45
-
-
Save rtanglao/463187 to your computer and use it in GitHub Desktop.
play gamelan sounds with your N900
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #---------------------------------------------------------------------------------- | |
| # | |
| # 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