/* A blip, laser, explosion, 8-bit synth, based heavily on a program called SFXR by DrPetter. * The SFXR website is here: http://www.cyd.liu.se/~tompe573/hp/project_sfxr.html * * This code is messy, but nonetheless (C) Ben Porter 2009. * Feel free to use in any way you wish but keep this copyright notice intake. */ import net.beadsproject.beads.core.*; import net.beadsproject.beads.data.*; import net.beadsproject.beads.data.buffers.*; import net.beadsproject.beads.ugens.*; import controlP5.*; ControlP5 controlP5; AudioContext ac; /** * When you click 'play' a UGen chain is created with the appropriate * structure and parameters. It is then attached to ac.out which plays it * immediately. The old UGen chain is removed before creating the new one. * * sample - the last UGen attached to ac.out. */ UGen sample = null; /* * Global enumerations. */ // generator types final int GT_SQUARE = 0; final int GT_SAW = 1; final int GT_SINE = 2; final int GT_NOISE = 3; // bit-depths final int BITS8 = 0; final int BITS16 = 1; // sample rates final int FORTYFOUR = 0; final int TWENTYTWO = 1; // misc constants final float NoiseMaxFreq = 6000.; /* * Parameters of the next sound to be synthesized. * Refer to the sfxr documentation * * Note that they have to be public for controlP5 to have access to them. */ public int SampleRate = FORTYFOUR; public int BitDepth = BITS16; public int GeneratorType = GT_SQUARE; public float Volume = 100.; public float AttackTime = 50.; public float SustainTime = 90.; public float SustainPunch = 1.; public float DecayTime = 460.; public float Frequency = 1350.0; public float MinFrequency = 50.0; public float Slide = 0.0; public float Curvature = 1.0; public float VibratoDepth = 0.; public float VibratoSpeed = 0.; public float ChangeAmount = 0.2; public float ChangeSpeed = 0.93; public float RepeatSpeed = 0.0; public float PhaserOffset = 0.0; public float PhaserSweep = 0.0; /* Set up the parameter ranges */ final float MaxAttackTime = 3000.; final float MaxSustainTime = 3000.; final float MaxDecayTime = 3000.; final float MaxSoundTime = MaxAttackTime + MaxSustainTime + MaxDecayTime; // gather Parameters into an array public float AllParams[] = {AttackTime,SustainTime,SustainPunch,DecayTime,Frequency,MinFrequency,Slide,Curvature,VibratoDepth,VibratoSpeed,ChangeAmount,ChangeSpeed,RepeatSpeed,PhaserOffset,PhaserSweep}; public float ParamRanges[][] = { { 0,MaxAttackTime }, { 0,MaxSustainTime }, { 1,5. }, { 0,MaxDecayTime }, { 0,3000 }, // freq { 0,500 }, //minfreq { -3,3 }, // slide { 0,5 }, // Curvature { 0,1 }, // VibratoDepth { 0,3 }, //Vibratopeed { -1.,1. }, // ChangeAmount { 0.,1. }, // ChangeSpeed { 0.,1. }, // RepeatSpeed { 0.,1.0 }, // PhaserOffset { -1.,1. } // PhaserSweep }; /* End parameters */ /* Some Funky Presets */ final int presetTypes[] = { 0,0,0,0,3,3,1,0,0,0,1,0}; final float presetParameters[][] = { { 45.0,105.0,1.0,315.0,690.0,27.5,0.0,1.0,0.0,0.0,0.49,0.965,0.0,0.0,0.0 }, { 45.0,105.0,2.0,405.0,1230.0,27.5,0.0,1.0,0.0,0.0,0.8299999,0.96,0.0,0.0,0.0 }, { 0.0,255.0,1.02,90.0,1185.0,25.0,-2.1,0.77500004,0.0,0.0,0.00999999,0.0,0.0,0.0,0.0 }, { 0.0,450.0,1.02,480.0,1575.0,40.0,-0.93000007,1.075,0.099999994,1.41,-0.28000003,0.945,0.78499997,0.0,0.0 }, { 0.0,585.0,3.24,480.0,1410.0,40.0,-1.5600001,0.975,0.0,0.0,0.0,0.0,0.0,0.0,0.0, }, { 0.0,585.0,4.62,1230.0,1410.0,17.5,-2.13,0.975,0.87,1.3349999,0.0,0.0,0.78,0.0,0.0 }, { 0.0,405.0,1.0,150.0,600.0,17.5,0.4499998,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, }, { 0.0,60.0,1.0,240.0,765.0,17.5,0.21000004,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 }, { 0.0,585.0,1.0,495.0,795.0,17.5,0.17999983,1.0,0.0,0.0,0.38,0.96999997,0.885,0.0,0.0 }, { 0.0,60.0,1.0,240.0,765.0,17.5,0.21000004,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 }, { 0.0,45.0,1.0,45.0,255.0,17.5,0.029999971,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 }, { 0.0,105.0,1.0,30.0,840.0,17.5,0.029999971,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 } }; // repeater: returns a UGen that // records numSamples from source and loops it infinitely // used for the pewpew lasers public UGen repeater(UGen source, int numSamples) { Sample s = new Sample(ac.getAudioFormat(),numSamples); Recorder rec = new Recorder(ac,s); rec.start(); rec.addInput(source); SamplePlayer sp = new SamplePlayer(ac,s); sp.addDependent(rec); sp.setLoopType(SamplePlayer.LoopType.LOOP_FORWARDS); return sp; } /*******************/ /*******************/ /*******************/ /*******************/ void setup() { size(325,330); background(color(0xC0,0xB0,0x90)); // load gui controlP5 = new ControlP5(this); controlP5.load("tight.xml"); controlP5.controller("presetlabel").setColorValue(0); controlP5.lock(); // create and start the AC ac = new AudioContext(512); ac.start(); } /** * This is where all the action is. */ public void play() { // regenerate sample based on the parameters if (sample!=null) { ac.out.removeAllConnections(sample); } float ScaledFrequency = Frequency; sample = null; switch (GeneratorType) { case GT_SQUARE: sample = new WavePlayer(ac,ScaledFrequency,new SquareBuffer().getDefault()); break; case GT_SAW: sample = new WavePlayer(ac,ScaledFrequency,new SawBuffer().getDefault()); break; case GT_SINE: sample = new WavePlayer(ac,ScaledFrequency,new SineBuffer().getDefault()); break; case GT_NOISE: ScaledFrequency = Frequency/NoiseMaxFreq; sample = new WavePlayer(ac,ScaledFrequency,new NoiseBuffer().generateBuffer((int)ac.msToSamples(1000.f))); break; }; float totalSoundLength = AttackTime+0.01+SustainTime+DecayTime; int totalSoundLengthSamples = (int)ac.msToSamples(totalSoundLength); int maxSoundLengthSamples = (int)ac.msToSamples(MaxSoundTime); // Frequency modulation UGen freq; Envelope freqEnv = new Envelope(ac,ScaledFrequency); float SlideSc = Slide*Slide; float MaxFreq = 22000.; float MinFreq = MinFrequency; if (GeneratorType==GT_NOISE) { MaxFreq/=NoiseMaxFreq; MinFreq/=NoiseMaxFreq; } // Frequency Sweep if (Slide > 0) freqEnv.addSegment(MaxFreq,1000./SlideSc,Curvature,null); else if (Slide < 0) freqEnv.addSegment(MinFreq,1000./SlideSc,Curvature,null); // Vibrato freq = new Mult(ac,freqEnv, new Add(ac, new Mult(ac, new WavePlayer(ac,VibratoSpeed*VibratoSpeed*50,new SineBuffer().getDefault()), //new WavePlayer(ac,1,new NoiseBuffer().getDefault()), //new Static(ac,1.0) new Static(ac,VibratoDepth) ), new Static(ac,1.)) ); // Add pitch change multiplier Envelope pitchChange = new Envelope(ac,1.f); float pitchChangeAmount = 1+ChangeAmount; float pitchChangeTime = (1-ChangeSpeed)*1000.; pitchChange.addSegment(1.f,pitchChangeTime); pitchChange.addSegment(pitchChangeAmount,0.01f); UGen pc = new Mult(ac,pitchChange,freq); // Add repeater int repeatSamples = 1+(int)(pow(1-RepeatSpeed,2)*maxSoundLengthSamples); UGen rep = repeater(pc,repeatSamples); ((WavePlayer)sample).setFrequencyEnvelope(rep); // Apply sweeping phaser float PhaserOffsetScaled = (float)ac.samplesToMs(PhaserOffset*1024*16); Envelope phaserEnvelope = new Envelope(ac,PhaserOffsetScaled); float phaserTarget = (float)ac.samplesToMs(PhaserSweep*10*MaxSoundTime + PhaserOffsetScaled); phaserTarget = max(0,phaserTarget); phaserEnvelope.addSegment(phaserTarget,MaxSoundTime); TapIn ti = new TapIn(ac,10000.); ti.addInput(sample); TapOut to = new TapOut(ac,ti,phaserEnvelope); ScalingMixer sm = new ScalingMixer(ac); sm.addInput(sample); sm.addInput(to); // Apply amplitude envelope // and limit to (-1,1) range Envelope volEnv = new Envelope(ac,0.f); volEnv.addSegment(Volume/1000.f,AttackTime); volEnv.addSegment(SustainPunch*Volume/1000.f,0.01f); volEnv.addSegment(Volume/1000.f,SustainTime,.8,null); volEnv.addSegment(0.f,DecayTime); Gain volume = new Gain(ac,1,volEnv); volume.addInput(sample); RangeLimiter rl = new RangeLimiter(ac,1); rl.addInput(volume); // Convert to 8 or 16-bit int numbits = BitDepth==BITS8?8:16; NBitsConverter ebp = new NBitsConverter(ac,numbits); ebp.addInput(rl); // Downsample if necessary if (SampleRate==TWENTYTWO) { UGen to22 = new UGen(ac,1,1){ public void calculateBuffer() { for(int i=0;i=0 && imaxp) p[i] = maxp; } } public void mutate() { // get the current set of params float p[] = getCurrentParameters(); mutateParameters(p,.05); setParameters(p); updateParams(); play(); } public void randomsound() { float p[] = new float[AllParams.length]; for(int i=0;i