Created
July 5, 2010 04:33
-
-
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
This file contains 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
# 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