void MainWindow::buttonSixPressed() { m_currentNote = 5; Note * note = m_sequencerController->getSequencer()->getNotes().at( 5 ); Oscillator * oscillator = note->getOscillator(); float frequency = oscillator->getFrequency(); float amplitude = note->getAmplitude(); blockSignals( true ); if( note->getWavetype() == FM ) { FmOscillator * fm = static_cast<FmOscillator *>( oscillator ); ui->harmonicitySpinner->setEnabled( true ); ui->modIndexSpinner->setEnabled( true ); ui->harmonicitySpinner->setValue( fm->getHarmonicity() ); ui->modIndexSpinner->setValue( fm->getModulationIndex() ); } else { ui->harmonicitySpinner->setEnabled( false ); ui->modIndexSpinner->setEnabled( false ); } ui->frequencySpinner->setValue( frequency ); ui->amplitudeSlider->setValue( amplitude * 100.0f ); ui->bpmBox->setValue( m_sequencerController->getBpm() ); setComboBox( note->getWavetype() ); blockSignals( false ); }
int main() { printf("Noisebox!\n"); osc.setOscType(kOSC_TYPE_SAW , SAMPLERATE); osc.frequency = 440; lfo.setOscType(kOSC_TYPE_SAW, SAMPLERATE); lfo.frequency = 0.1; if(startMidi()!=0) { return 1; } if(startAudio()!=0) { return 1; } cout << "\nPlaying ... press any to quit.\n"; while ( cin.peek() == EOF ) { usleep(100*1000); } printf("Bye!\n"); }
// --------------------------------------------------------------------------- // accum_samples // --------------------------------------------------------------------------- // helper // static void accum_samples( CSOUND * csound, Oscillator & oscil, Breakpoint & bp, double * bufbegin ) { if( bp.amplitude() > 0 || oscil.amplitude() > 0 ) { double radfreq = radianFreq( csound, bp.frequency() ); double amp = bp.amplitude(); double bw = bp.bandwidth(); // initialize the oscillator if it is changing from zero // to non-zero amplitude in this control block: if ( oscil.amplitude() == 0. ) { // don't initialize with bogus values, Oscillator // only guards against out-of-range target values // in generateSamples(), parameter mutators are // dangerous: if ( radfreq > PI ) // don't alias amp = 0.; if ( bw > 1. ) // clamp bandwidth bw = 1.; else if ( bw < 0. ) bw = 0.; #ifdef DEBUG_LORISGENS /* std::cerr << "initializing oscillator " << std::endl; std::cerr << "parameters: " << bp.frequency() << " "; std::cerr << amp << " " << bw << std::endl; */ #endif // initialize frequency, amplitude, and bandwidth to // their target values: /* oscil.setRadianFreq( radfreq ); oscil.setAmplitude( amp ); oscil.setBandwidth( bw ); */ oscil.resetEnvelopes( bp, (double) csound->esr ); // roll back the phase: oscil.resetPhase( bp.phase() - ( radfreq * (double) csound->ksmps ) ); } // accumulate samples into buffer: // oscil.generateSamples( bufbegin, bufbegin + nsamps, radfreq, amp, bw ); oscil.oscillate( bufbegin, bufbegin + csound->ksmps, bp, (double) csound->esr ); } }
////////////////////////////////////////// // the magic int audioCallback( void *outputBuffer, void *inputBuffer, unsigned int length, double streamTime, RtAudioStreamStatus status, void *userData ) { float *buffer = (float *) outputBuffer; if ( status ) std::cout << "Stream underflow detected!" << std::endl; float out = 0; for(int i = 0; i < length; i++) { float of = oscFreq.get(); lfo.frequency = lfoFreq.get(); if(modType==MOD_PITCH) { osc.frequency = of - modAmount.get()*map(lfo.getSample(), -1, 1, 0, of); } else { osc.frequency = of; } float filtFreq = filterFreq.get(); if(modType==MOD_CUTOFF) { filtFreq = filtFreq - modAmount.get()*map(lfo.getSample(), -1, 1, 40, filtFreq); } float s = osc.getSample(); out = filter.lores(s, filtFreq, filterRes.get()); out = distort(out*distVolume); if(out!=out) { // NaN prevention out = s; } out *= 0.7f; if(mute) out = 0; buffer[i*2] = out; buffer[i*2+1] = out; } return 0; }
//This function shows a part of how the modules work internally, based on a sample-by-sample model. void modularSynthInternals(void) { //Here we create an Oscillator Oscillator osc; osc.frequency = 1; //We'll set the frequency to 1 Hz osc.setGeneratorFunction(Oscillator::sine); //Set the waveform to a sine wave. //We are going to manually tell the oscillator that the sample rate is 40 samples per second ModuleControlData_t controlData; controlData.sampleRate = 40; osc.setData(controlData); //If the frequency is 1 Hz (1 cycle per second) and there are 40 samples per second, if we take 40 samples, //we should expect to see a whole sine wave (0 to 1 to 0 to -1 and back to 0). So, we call getNextSample() //40 times to advance 40 samples through the process of generating the waveform and print the result. for (int i = 0; i < 40; i++) { cout << osc.getNextSample() << endl; } }
////////////////////////////////////////// // The main midi callback void midiCallback( double deltatime, std::vector< unsigned char > *message, void *userData ) { unsigned int nBytes = message->size(); for ( unsigned int i=0; i<nBytes; i++ ) std::cout << "Byte " << i << " = " << (int)message->at(i) << ", "; if ( nBytes > 0 ) std::cout << "stamp = " << deltatime << std::endl; if(message->at(0)==144) { // note on mute = false; int oscType = message->at(1) - 36; oscType %= 4; osc.setOscType(oscType, SAMPLERATE); } else if(message->at(0)==128) { // note off if(message->at(1)<=39) { mute = true; } } else if(message->at(0)==176) { int val = message->at(2); switch(message->at(1)) { case 1: oscFreq.set(logMap(val, 0, 127, 20, 8000)); break; case 2: lfoFreq.set(logMap(val, 0, 127, 0.01, 100)); break; case 3: modAmount.set(map(val, 0, 127, 0, 1)); break; case 4: if(val>63) { modType = MOD_PITCH; } else { modType = MOD_CUTOFF; } break; case 5: filterFreq.set(map(val, 0, 127, 50, 4000)); break; case 6: filterRes.set(map(val, 0, 127, 1, 10)); break; case 7: distVolume = logMap(val, 0, 127, 0, 10); break; case 8: distGain = logMap(val, 0, 127, 0, 10); break; } } }
void processAudio(AudioBuffer &buffer) { FloatArray left = buffer.getSamples(LEFT_CHANNEL); FloatArray right = buffer.getSamples(RIGHT_CHANNEL); for(int i = 0; i<buffer.getSize(); i++){ if(abs(last-target) < 0.001){ last = target; target = noise->getNextSample()*range; } left[i] = last; last += getIncrement(); right[i] = hz.voltsToSample(quantize(hz.sampleToVolts(right[i]))); } }
int main( int argc, char ** argv ) { if( argc <= 2 ) { std::cout << "please provide valid command line arguments. Syntax is '/wav_writer <filename.wav> <oscillatortype>'" << std::endl; return -1; } std::string filename; filename = "res/"; filename += argv[1]; Oscillator * oscillator; Oscillator * oscillatorTwo = 0; if( strcmp( argv[2], "triangle" ) == 0 ) { oscillator = new TriangleOscillator(); } else if( strcmp( argv[2], "rsaw" ) == 0 ) { oscillator = new RisingSawtoothOscillator(); } else if( strcmp( argv[2], "additive" ) == 0 ) { oscillator = new SineOscillator(); oscillatorTwo = new SineOscillator( 523.0f ); } else { oscillator = new SineOscillator(); } WavWriter wavWriter( filename ); wavWriter.setBitsPerSample( 16 ); wavWriter.setStereo( false ); int dataSize = 5 * oscillator->getSampleRate() * 2; // duration in seconds * sample rate * bytes per sample char * data = new char[dataSize]; if( oscillatorTwo != 0 ) { for( int i = 0; i < dataSize - 1; i+=2 ) { ByteConverter::shortToBytes( oscillator->nextSample() / 2 + oscillatorTwo->nextSample() / 2, data, i ); } } else { for( int i = 0; i < dataSize - 1; i+=2 ) { ByteConverter::shortToBytes( oscillator->nextSample(), data, i ); } } if( wavWriter.writeWav( data, dataSize ) ) { std::cout << "hooray! it worked!" << std::endl; } else { std::cout << "aww, no worky." << std::endl; } delete oscillator; if( oscillatorTwo != 0 ) { delete oscillatorTwo; } return 0; }
float getNextSample(){ float vca1 = sine->getNextSample(); vca1 += chirp->getNextSample(); vca1 *= env1->getNextSample(); float vca2 = 0.0f; vca2 += impulse->getNextSample(); // vca2 += filter->process(noise->getNextSample()); // vca2 *= env2->getNextSample(); vca2 += noise->getNextSample(); vca2 = filter->process(vca2); vca2 *= env2->getNextSample(); float sample = vca1*(1.0-balance) + vca2*balance; return sample; }
//-------------------------------------------------------------- void testApp::mousePressed(int x, int y, int button){ Oscillator newOsc; newOsc.setup(50); osc.push_back(newOsc); }
void runExperiment(void) { Input.setup(true, true); StreamOutput output; //StreamOutput is one of the ways to get sound out of a modular synth. //It requires a CX_SoundStream to play the sounds, which is configured below. //Configure the sound stream. See the soundBuffer example for more information about these values. //Also see the documentation for CX_SoundStream::Configuration. CX_SoundStream::Configuration ssConfig; ssConfig.api = RtAudio::Api::WINDOWS_DS; ssConfig.outputChannels = 2; ssConfig.sampleRate = 48000; ssConfig.bufferSize = 4096; ssConfig.streamOptions.numberOfBuffers = 2; CX_SoundStream ss; ss.setup(ssConfig); ss.start(); output.setup(&ss); //Set the CX_SoundStream ss as the sound stream for the StreamOutput. //Now that we have an output, we can make a really basic synthesizer: Oscillator osc; osc.setGeneratorFunction(Oscillator::saw); //We'll generate a saw wave. osc.frequency = 440; //At 440 Hz (A4) Multiplier gain; gain.setGain(-20); //Make the output quieter by 20 decibels osc >> gain >> output; //operator>> means that osc feeds into gain which then feeds into output. cout << "Let's listen to a saw wave for 3 seconds" << endl; Clock.sleep(CX_Seconds(3)); //Lets add a low pass filter to the chain. Filter lpf; lpf.setType(Filter::LOW_PASS); lpf.cutoff = 600; //Set the cutoff frequency of the filter to 600 Hz, so frequencies past there get attentuated. osc >> lpf >> gain >> output; //Reconnect things so that the osc goes through the filter. cout << "Now a filtered saw" << endl; Clock.sleep(CX_Seconds(3)); //Lets add an envelope Envelope env; env.a = 0.5; //Set the attack time to .5 seconds (i.e. 500 ms). This is the length of time needed to go from 0 to 1. env.d = 0.5; //Decay time, to go from 1 to the sustain level env.s = 0.4; //Sustain at .4 times the full amplitude, which is reached at the end of the attack env.r = 1.0; //Release time, time to go from the sustain level to 0 osc >> lpf >> env >> gain >> output; cout << "Now an amp envelope on the sound will give it a slow onset on offset." << endl; env.attack(); Clock.sleep(CX_Seconds(3)); env.release(); Clock.sleep(CX_Seconds(2)); /* You can route the output from a modular synth into a SoundBufferOutput, which allows you to use the sounds you make in that same way that you would use a sound buffer, including saving them to a file. */ SoundBufferOutput sbOut; gain >> sbOut; //Without changing the other connections, route gain into sbOut, disconnecting it from output. sbOut.setup(44100); //Use the same sample rate as the sound stream env.attack(); //Start by priming the evelope so that sound comes out of it. sbOut.sampleData(CX_Seconds(2)); //Sample 1 second worth of data at the given sample rate. env.release(); //Now relase the evelope (go from the sustain phase to the release phase sbOut.sampleData(CX_Seconds(1)); //And sample an additional 1/2 second of data. //Now that you're done sampling, you can use the sound buffer that you made! sbOut.sb; // <-- This is the sound buffer. See the soundBuffer example for to see how to use it in detail. sbOut.sb.normalize(); //Its a good idea to normalize before saving to a file to get the levels up. sbOut.sb.writeToFile("Envelope sample.wav"); //You can save it to file, like in this example, or play it using a CX_SoundBufferPlayer. //Now we make a relatively complex synthesizer, with two oscillators, an LFO //modifying the frequency of one of the oscillators, an envelope modifying the cutoff frequency //of the filter, and a mixer to combine together the oscillators. Mixer oscMix; osc >> gain >> oscMix; //Run the main oscillator into the mixer. //This oscillator doubles the main oscillator, except that its frequency is modified by an LFO. Oscillator doublingOsc; doublingOsc.setGeneratorFunction(Oscillator::saw); Oscillator lfo; lfo.setGeneratorFunction(Oscillator::sine); lfo.frequency = 5; Multiplier lfoGain; lfoGain.amount = 2; Adder lfoOffset; lfoOffset.amount = osc.frequency; //Feed to lfo signal (which goes from -1 to 1) into a multiplier to make its range a little bigger, then add an offset to put //it into a good frequency range. This offset will be changed along with the mainOsc frequency. lfo >> lfoGain >> lfoOffset >> doublingOsc.frequency; Multiplier doublingOscGain; doublingOsc >> doublingOscGain >> oscMix; //Now run the doubliing oscillator into the mixer. //Run a mod envelope into the filter cutoff frequency. Envelope modEnv; modEnv.a = .1; modEnv.d = .1; modEnv.s = .5; modEnv.r = .2; Multiplier modMult; modMult.amount = 1000; Adder modOffset; modOffset.amount = 400; modEnv >> modMult >> modOffset >> lpf.cutoff; //Change the amp envelope settings a little env.a = .3; env.d = .2; env.s = .6; env.r = .2; //After the mixer, filter to mixed data, attach the amp envelope, and route into the output. oscMix >> lpf >> env >> output; drawInformation(); while (true) { if (Input.pollEvents()) { while (Input.Mouse.availableEvents()) { CX_Mouse::Event ev = Input.Mouse.getNextEvent(); if (ev.type == CX_Mouse::MOVED || ev.type == CX_Mouse::DRAGGED) { osc.frequency = pow(ev.x, 1.3); lfoOffset.amount = osc.frequency; //We don't set the frequency of the doubling osc directly, //instead we set the offset for the lfo that feeds into the frequency of the doubling osc. double g = -ev.y / 20; gain.setGain(g); doublingOscGain.setGain(g); cout << "Frequency = " << osc.frequency.getValue() << endl; cout << "Gain = " << g << endl; } if (ev.type == CX_Mouse::PRESSED) { env.attack(); modEnv.attack(); } if (ev.type == CX_Mouse::RELEASED) { env.release(); modEnv.release(); } } while (Input.Keyboard.availableEvents()) { CX_Keyboard::Event ev = Input.Keyboard.getNextEvent(); ss.hasSwappedSinceLastCheck(); while (!ss.hasSwappedSinceLastCheck()) ; switch (ev.key) { case 'T': osc.setGeneratorFunction(Oscillator::triangle); doublingOsc.setGeneratorFunction(Oscillator::triangle); break; case 'Q': osc.setGeneratorFunction(Oscillator::square); doublingOsc.setGeneratorFunction(Oscillator::square); break; case 'I': osc.setGeneratorFunction(Oscillator::sine); doublingOsc.setGeneratorFunction(Oscillator::sine); break; case 'A': osc.setGeneratorFunction(Oscillator::saw); doublingOsc.setGeneratorFunction(Oscillator::saw); break; case 'W': osc.setGeneratorFunction(Oscillator::whiteNoise); doublingOsc.setGeneratorFunction(Oscillator::whiteNoise); break; } } drawInformation(); } } }
void init_audio_synth() { AudioOutput::Buffer buf; buf.dataSize = BUFFER_SIZE * CHANNEL_NUM * sizeof(int16_t); buf.data = (uint8_t *)&g_outBuf[0][0]; g_audioOut.add_buffer(&buf); buf.data = (uint8_t *)&g_outBuf[1][0]; g_audioOut.add_buffer(&buf); g_audioOut.set_source(&g_audioOutConverter); AudioBuffer audioBuf(&g_audioBuf[0], BUFFER_SIZE); g_audioOutConverter.set_buffer(audioBuf); g_audioOutConverter.set_source(&g_mixer); g_kickSeq.set_sample_rate(kSampleRate); g_kickSeq.set_tempo(100.0f); // g_kickSeq.set_sequence("x---x---x---x-x-x---x---x---x---xx--x--x--xxx-x-"); g_kickSeq.set_sequence("x---------x---------"); //x-x----xx---"); g_kickSeq.init(); g_kickGen.set_sample_rate(kSampleRate); g_kickGen.set_sequence(&g_kickSeq); g_kickGen.set_freq(50.0f); g_kickGen.enable_sustain(false); g_kickGen.init(); g_kickGen.set_attack(0.01f); g_kickGen.set_release(0.6f); g_bassSeq.set_sample_rate(kSampleRate); g_bassSeq.set_tempo(100.0f); g_bassSeq.set_sequence("--s>>>>p--------"); //"--s>>>p-----s>>>>>>p----"); g_bassSeq.init(); g_bassGen.set_sample_rate(kSampleRate); g_bassGen.set_sequence(&g_bassSeq); g_bassGen.set_freq(80.0f); g_bassGen.enable_sustain(true); g_bassGen.init(); g_bassGen.set_attack(0.3f); g_bassGen.set_release(3.0f); g_filter.set_sample_rate(kSampleRate); g_filter.set_frequency(120.0f); g_filter.set_q(0.4f); g_filter.recompute_coefficients(); g_filter.set_input(&g_bassGen); g_delay.set_sample_rate(kSampleRate); g_delay.set_maximum_delay_seconds(0.4f); g_delay.set_delay_samples(g_kickSeq.get_samples_per_beat()); g_delay.set_feedback(0.7f); g_delay.set_wet_mix(0.5f); g_delay.set_dry_mix(0.8f); g_delay.set_input(&g_kickGen); AudioBuffer mixBuf(&g_mixBuf[0], BUFFER_SIZE); g_mixer.set_buffer(mixBuf); g_mixer.set_input_count(2); g_mixer.set_input(0, &g_delay, 0.5f); g_mixer.set_input(1, &g_bassGen, 0.34f); // g_mixer.set_input(2, &g_tickGen, 0.3f); }