1#!/usr/bin/python2.5 2# 3# Copyright 2012 Olivier Gillet. 4# 5# Author: Olivier Gillet (ol.gillet@gmail.com) 6# 7# Permission is hereby granted, free of charge, to any person obtaining a copy 8# of this software and associated documentation files (the "Software"), to deal 9# in the Software without restriction, including without limitation the rights 10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11# copies of the Software, and to permit persons to whom the Software is 12# furnished to do so, subject to the following conditions: 13# 14# The above copyright notice and this permission notice shall be included in 15# all copies or substantial portions of the Software. 16# 17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23# THE SOFTWARE. 24# 25# See http://creativecommons.org/licenses/MIT/ for more information. 26# 27# ----------------------------------------------------------------------------- 28# 29# Waveform definitions. 30 31import numpy 32 33 34"""---------------------------------------------------------------------------- 35Waveforms for vowel synthesis 36----------------------------------------------------------------------------""" 37 38SAMPLE_RATE = 96000 39 40waveforms = [] 41# Create amplitude modulated sine/square tables for formants. 42sine_samples = [] 43square_samples = [] 44sine = numpy.sin(numpy.arange(16.0) / 16.0 * 2 * numpy.pi) 45for i, x in enumerate(sine): 46 gains = numpy.exp(0.184 * numpy.arange(16.0)) 47 gains[0] = 0 48 values = gains * x * 4 49 values = numpy.round(values).astype(int) 50 amps = numpy.round(gains) 51 if (i >= 8): 52 amps = -amps 53 square_samples.extend(amps.astype(int)) 54 sine_samples.extend(values) 55 56waveforms.extend([ 57 ('formant_sine', sine_samples), 58 ('formant_square', square_samples) 59]) 60 61 62"""---------------------------------------------------------------------------- 63Band-limited waveforms 64----------------------------------------------------------------------------""" 65 66WAVETABLE_SIZE = 256 67 68# The Juno-6 / Juno-60 waveforms have a brighter harmonic content, which can be 69# recreated by adding to the signal a 1-pole high-pass filtered version of 70# itself. 71JUNINESS = 1.0 72 73 74def dither(x, order=0, type=numpy.int16): 75 for i in xrange(order): 76 x = numpy.hstack((numpy.zeros(1,), numpy.cumsum(x))) 77 x = numpy.round(x) 78 for i in xrange(order): 79 x = numpy.diff(x) 80 if any(x < numpy.iinfo(type).min) or any(x > numpy.iinfo(type).max): 81 print 'Clipping occurred!' 82 x[x < numpy.iinfo(type).min] = numpy.iinfo(type).min 83 x[x > numpy.iinfo(type).max] = numpy.iinfo(type).max 84 return x.astype(type) 85 86 87def scale(array, min=-32766, max=32766, center=True, dither_level=2): 88 if center: 89 array -= array.mean() 90 mx = numpy.abs(array).max() 91 array = (array + mx) / (2 * mx) 92 array = array * (max - min) + min 93 return dither(array, order=dither_level) 94 95 96# Sine wave. 97sine = -numpy.sin(numpy.arange(WAVETABLE_SIZE + 1) / float(WAVETABLE_SIZE) * \ 98 2 * numpy.pi) * 127.5 + 127.5 99 100# Band limited waveforms. 101num_zones = 15 102bl_pulse_tables = [] 103bl_tri_tables = [] 104 105wrap = numpy.fmod( 106 numpy.arange(WAVETABLE_SIZE + 1) + WAVETABLE_SIZE / 2, 107 WAVETABLE_SIZE) 108 109quadrature = numpy.fmod( 110 numpy.arange(WAVETABLE_SIZE + 1) + WAVETABLE_SIZE / 4, 111 WAVETABLE_SIZE) 112 113fill = numpy.fmod( 114 numpy.arange(WAVETABLE_SIZE + 1), 115 WAVETABLE_SIZE) 116 117waveforms.append(('sine', scale(sine[quadrature]))) 118 119for zone in range(num_zones): 120 f0 = 440.0 * 2.0 ** ((18 + 8 * zone - 69) / 12.0) 121 if zone == num_zones - 1: 122 f0 = SAMPLE_RATE / 2.0 - 1 123 else: 124 f0 = min(f0, SAMPLE_RATE / 2.0) 125 period = SAMPLE_RATE / f0 126 m = 2 * numpy.floor(period / 2) + 1.0 127 i = numpy.arange(-WAVETABLE_SIZE / 2, WAVETABLE_SIZE / 2) / \ 128 float(WAVETABLE_SIZE) 129 pulse = numpy.sin(numpy.pi * i * m) / (m * numpy.sin(numpy.pi * i) + 1e-9) 130 pulse[WAVETABLE_SIZE / 2] = 1.0 131 pulse = pulse[fill] 132 133 bl_pulse_tables.append(('bandlimited_comb_%d' % zone, 134 scale(pulse[quadrature]))) 135 136waveforms.extend(bl_pulse_tables) 137waveforms.extend(bl_tri_tables) 138 139 140"""---------------------------------------------------------------------------- 141Wavetables 142-----------------------------------------------------------------------------""" 143 144wavetable_data = [] 145waves = map(ord, file('braids/data/waves.bin', 'rb').read()) 146wavetable_data.append(('waves', waves)) 147 148wave_map = map(ord, file('braids/data/map.bin', 'rb').read()) 149wavetable_data.append(('map', wave_map)) 150 151 152 153"""---------------------------------------------------------------------------- 154??? 155-----------------------------------------------------------------------------""" 156 157random_data = [ 1585, 0, 132, 0, 20, 16, 20, 81, 16, 65, 8, 17, 4, 65, 17, 5, 1590, 69, 1, 88, 17, 25, 0, 132, 144, 0, 64, 80, 0, 21, 148, 0, 16065, 17, 5, 129, 4, 1, 68, 1, 65, 5, 65, 17, 21, 4, 20, 16, 1614, 128, 80, 0, 4, 64, 20, 21, 0, 4, 1, 20, 16, 9, 17, 68, 16217, 5, 17, 4, 1, 132, 0, 65, 16, 20, 81, 145, 1, 81, 17, 21, 16316, 21, 81, 1, 20, 16, 21, 68, 16, 16, 144, 5, 0, 132, 17, 4, 16465, 68, 129, 65, 20, 81, 129, 0, 4, 20, 65, 129, 17, 5, 80, 5, 16564, 64, 1, 132, 64, 65, 17, 68, 65, 64, 17, 5, 80, 0, 4, 1, 16620, 16, 25, 64, 4, 17, 4, 20, 16, 84, 20, 128, 5, 0, 132, 0, 16765, 80, 1, 65, 24, 81, 0, 129, 80, 129, 17, 5, 64, 1, 65, 64, 16816, 64, 16, 64, 17, 5, 64, 1, 65, 17, 5, 17, 132, 5, 80, 1, 16964, 20, 1, 16, 25, 81, 0, 80, 4, 129, 16, 5, 0, 4, 20, 16, 1704, 0, 8, 16, 4, 1, 20, 81, 16, 69, 1, 8, 21, 72, 0, 80, 1714, 65, 1, 0, 80, 1, 65, 0, 64, 80, 65, 17, 4, 20, 20, 129, 1721, 4, 21, 20, 16, 132, 17, 5, 16, 8, 1, 4, 4, 64, 0, 4, 1735, 17, 21, 81, 0, 5, 128, 0, 65, 64, 17, 4, 80, 16, 68, 0, 1744, 1, 1, 89, 17, 21, 64, 80, 1, 145, 0, 68, 20, 69, 1, 88, 17517, 25, 0, 132, 16, 65, 80, 1, 81, 1, 4, 21, 16, 21, 1, 16, 1769, 21, 20, 128, 4, 0, 69, 16, 20, 16, 21, 81, 65, 8, 20, 4, 17764, 64, 1, 132, 21, 145, 1, 64, 24, 64, 16, 4, 80, 65, 1, 9, 1785, 1, 4, 65, 4, 21, 64, 1, 81, 16, 16, 144, 17, 4, 1, 4, 1795, 65, 20, 128, 80, 9, 5, 1, 4, 1, 88, 0, 64, 8, 81, 80, 1801, 81, 17, 0, 145, 17, 69, 1, 4, 4, 17, 4, 9, 21, 20, 128, 18181, 84, 17, 64, 17, 68, 16, 8, 16, 20, 81, 0, 21, 20, 128, 144, 1825, 21, 0, 4, 1, 132, 64, 129, 1, 64, 80, 1, 65, 1, 5, 1, 1831, 9, 9, 81, 64, 17, 64, 20, 68, 1, 24, 0, 4, 5, 65, 69, 18465, 1, 68, 16, 8, 81, 4, 5, 65, 64, 65, 17, 8, 64, 0, 64, 18580, 1, 68, 0, 24, 5, 85, 4, 65, 64, 80, 16, 64, 64, 17, 64, 18620, 128, 80, 65, 1, 24, 69, 21, 1, 20, 65, 4, 129, 17, 5, 65, 1871, 68, 16, 68, 1, 24, 0, 20, 81, 0, 5, 65, 1, 64, 17, 21, 1884, 1, 1, 25, 81, 20, 64, 64, 16, 65, 80, 17, 0, 145, 1, 65, 1890, 64, 20, 16, 20, 80, 64, 65, 17, 88, 0, 64, 24, 0, 4, 5, 19065, 17, 0, 145, 17, 4, 65, 4, 145, 65, 4, 65, 0, 80, 17, 5, 19180, 0, 4, 1, 1, 89, 0, 64, 4, 65, 8, 81, 80, 0, 88, 0, 19264, 64, 0, 8, 17, 133, 65, 8, 64, 80, 64, 0, 24, 1, 5, 80, 19317, 5, 8, 21, 0, 20, 81, 0, 149, 5, 0, 132, 0, 20, 16, 20, 19481, 16, 65, 24, 16, 4, 65, 17, 5, 81, 1, 20, 17, 0, 88, 0, 19564, 20, 16, 9, 5, 1, 4, 1, 8, 81, 17, 5, 65, 24, 65, 16, 19664, 80, 0, 4, 64, 4, 128, 80, 65, 1, 8, 64, 5, 5, 65, 20, 197128, 80, 25, 16, 21, 81, 0, 21, 1, 16, 9, 64, 64, 16, 64, 20, 19884, 16, 16, 144, 20, 0, 21, 16, 68, 16, 65, 9, 16, 20, 81, 16, 1998, 25, 16, 20, 81, 0, 5, 17, 4, 1, 68, 1, 0, 80, 5, 0, 2004, 65, 132, 65, 4, 5, 65, 4, 129, 5, 0, 132, 1, 20, 81, 17, 2015, 65, 17, 0, 145, 16, 5, 0, 20, 145, 16, 69, 16, 132, 20, 20, 20265, 80, 17, 68, 1, 8, 20, 8, 25, 20, 81, 0, 68, 1, 0, 80, 20316, 65, 64, 1, 65, 1, 5, 20, 20, 129, 1, 65, 17, 21, 84, 4, 20464, 21, 1, 16, 9, 64, 68, 64, 65, 17, 8, 0, 20, 81, 16, 9, 20516, 4, 5, 129, 5, 0, 68, 1, 145, 1, 65, 17, 5, 80, 16, 64, 2061, 8, 16, 4, 1, 4, 20, 16, 20, 144, 64, 9, 21, 16, 4, 65, 20717, 5, 64, 0, 88, 0, 64, 8, 65, 17, 21, 81, 81, 16, 16, 144, 208144, 0, 4, 80, 1, 20, 64, 20, 24, 16, 4, 0, 20, 81, 16, 4, 20980, 0, 24, 81, 0, 129, 16, 5, 0, 20, 81, 17, 5, 17, 4, 128, 21080, 65, 1, 24, 16, 5, 20, 0, 20, 0, 4, 1, 68, 0, 24, 0, 2114, 80, 16, 4, 64, 9, 16, 4, 65, 17, 21, 9, 25, 80, 64, 65, 2121, 24, 81, 0, 129, 16, 81, 0, 21, 80, 24, 0, 20, 81, 1, 144, 21380, 89, 0, 64, 8, 16, 4, 5, 129, 20, 20, 128, 17, 5, 16, 88, 2140, 64, 8, 65, 17, 21, 81, 81, 16, 16, 144, 4, 0, 69, 16, 20, 21516, 21, 0, 20, 81, 1, 20, 16, 25, 1, 5, 80, 64, 89, 80, 16, 21664, 1, 5, 20, 20, 65, 16, 16, 144, 5, 0, 132, 1, 64, 80, 16, 21784, 20, 20, 64, 4, 129, 5, 4, 17, 84, 17, 69, 1, 24, 0, 4, 21821, 16, 20, 80, 17, 0, 145, 16, 5, 84, 0, 128, 5, 0, 132, 1, 2194, 65, 64, 65, 1, 5, 64, 16, 16, 144, 16, 5, 0, 4, 85, 16, 22017, 65, 0, 8, 0, 4, 5, 17, 4, 17, 68, 65, 64, 65, 17, 4, 22116, 1, 24, 81, 20, 64, 64, 16, 65, 144, 16, 5, 0, 4, 4, 64, 22216, 65, 4, 65, 20, 64, 16, 16, 144, 5, 0, 4, 85, 16, 17, 65, 2230, 24, 0, 20, 16, 9, 64, 21, 81, 1, 65, 1, 5, 0, 4, 5, 22480, 0, 68, 65, 16, 16, 80, 255 225] 226 227wavetable_data.append(('code', random_data)) 228