Skip to content

Instantly share code, notes, and snippets.

@rtanglao
Created July 5, 2010 04:33
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save rtanglao/463996 to your computer and use it in GitHub Desktop.
python script to play gamelan sounds on your N900 based on GPS jitter
# Based on PygSoundTestTest_3.py by Matthew N. Brown
#
# PygSoundTestTest Copyright (C) 2009, 2010 by Matthew N. Brown
# N900 / Maemo Modifications and change to gpsgamelan.py Copyright 2010 by Roland Tanglao
# gpsgamelan.py 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 this file If not, see <http://www.gnu.org/licenses/>.
import location
import gobject
import pygame
import sys
from pygame.locals import *
import Numeric
import random
import os
import math
import time
from pygame import scrap
from Numeric import *
pygame_noteyish_sound = []
## 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)
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('GPSGamelan copyright 2010 by Roland Tanglao')
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.
global pygame_noteyish_sound
for n in range(0, len(noteyish)):
pygame_noteyish_sound += [generate_numpy_sound_data__draw_numpy_sound_data__and__return_pygame_sound__hehe( noteyish[n] )]
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
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
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 )
###### convert "numpy_sound_data" to pygame.mixer.Sound
print "Generating sound"
sound_thing = numpy_sound__converted_to_a__pygame_sound( numpy_sound_data )
return sound_thing
def numpy_sound__converted_to_a__pygame_sound(numpy_sound_data):
return pygame.sndarray.make_sound(numpy_sound_data)
def END():
print ''
print 'Program ended?'
print "###############################################################################"
print "###############################################################################"
print ''
pygame.quit()
raise SystemExit, ''
def on_error(control, error, data):
print "location error: %d... quitting" % error
data.quit()
def on_changed(device, data):
global pygame_noteyish_sound
if not device:
return
if device.fix:
if device.fix[1] & location.GPS_DEVICE_LATLONG_SET:
lat = device.fix[4]
long = device.fix[5]
# Compute GPS jitter from lat/long 1/10000
tone_long = int ((abs(long) * 10000) % 10)
tone_lat = int ((abs(lat) * 10000) % 10)
print "lat = %f, long = %f" % device.fix[4:6]
print "tone_long = %d tone_lat = %d" % (tone_long, tone_lat)
# play 2 random gamelan notes based on GPS jitter from lat and long
pygame.mixer.find_channel(True).play(pygame_noteyish_sound[tone_lat], 0)
pygame.mixer.find_channel(True).play(pygame_noteyish_sound[tone_long+10], 0)
def on_stop(control, data):
print "quitting from on_stop()"
data.quit()
def start_location(data):
data.start()
return False
print "Starting!"
HE_HE_init()
Lets_ROLL()
loop = gobject.MainLoop()
control = location.GPSDControl.get_default()
device = location.GPSDevice()
print "Looking for location"
control.set_properties(preferred_method=location.METHOD_USER_SELECTED,
preferred_interval=location.INTERVAL_DEFAULT)
control.connect("error-verbose", on_error, loop)
device.connect("changed", on_changed, control)
control.connect("gpsd-stopped", on_stop, loop)
gobject.idle_add(start_location, control)
loop.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment