//-------------------------------------------------------------- void ofApp::mousePressed(int x, int y, int button){ if (y< TOP_MARGIN && x>LEFT_MARGIN) { for (unsigned int i = 0; i < horizontalOscilators.size(); i++) {//this goes through the horizontal oscillators checking if anyone has been clicked over. if(horizontalOscilators[i].checkOver(x, y)){ setPressedOscilator(i, true); break; } } if (!bSelectedOscHor) {//in case that no oscillator was clicked then create a new one at the position of the mouse. horizontalOscilators.push_back(oscillator()); horizontalOscilators.back().setup(x, y); } }else if(y>TOP_MARGIN && x<LEFT_MARGIN){ for (unsigned int i = 0; i < verticalOscilators.size(); i++) { if(verticalOscilators[i].checkOver(x, y)){ setPressedOscilator(i, false); break; } } if (!bSelectedOscVert) { verticalOscilators.push_back(oscillator()); verticalOscilators.back().setup(x, y); } }else { bScaleMouse=true; } }
void writeStream(PaStream *handle, float frequency, float duration, float amplitude) { int i,j,dur, count = 0; dur = duration*44100/256; float index, index2, control, cr, *buf, *wave; cr = 44100/256; index = 0.f; buf = (float*) malloc(256*sizeof(float)); wave = sine_table(2048, 0); for(j = 0;j < dur;j++){ oscillator(buf, frequency+oscillator(&control,5.f,5.f, wave, &index2,2048, 1,cr),envelope(duration,cr,&count)*amplitude,wave,&index,2048,256,44100); Pa_WriteStream(handle, buf, 256); } free(buf); free(wave); }
/*! \internal \fn void Bouncer::animate(QPainter *painter,SelectedItem *item,qreal percent) */ void Bouncer::animate(QPainter *painter,SelectedItem *item,qreal percent) { GridItem *currentItem = item->current(); if ( !currentItem ) { return; } int imageSize = currentItem->selectedImageSize(); // Create an oscillator which will produce a sin wave whose lower bound is the // first parameter (i.e. the lowest dimension the image will take, and whose // upper bound is the second parameter (i.e. the highest dimension the image // will take). Oscillator oscillator(imageSize + minVariation * imageSize, imageSize + maxVariation * imageSize, frameMax, // upper bound of x SPEED_FACTOR, imageSize); // Ask the oscillator to produce a suitable width/height value for this stage // of the animation. int y = qRound(oscillator(percent*frameMax)); if (((y-imageSize) % 2) != 0) { y -= 1; } painter->setRenderHint(QPainter::SmoothPixmapTransform); //lazy man's version of mipmapping if (y > imageSize) { if (!bigpixmap.isNull()) draw(painter,bigpixmap,item,y,y); } else { const QPixmap &pixmap = currentItem->selectedPic(); if ( !(pixmap.isNull()) ) { draw(painter,pixmap,item,y,y); } } }
void testMidiWithSimpleSquare() { Audio::init(); Synth::Misc::SimpleSquare oscillator(Audio::SAMPLE_RATE, 10000); Midi::init(); Midi::BasicMsg midiMsg; Display::clearScreen(); Display::writeString("Display test!",0); Display::carryOutAllActionsInQueue(); Time::delayS(0.5); Display::carryOutAllActionsInQueue(); int16_t sample = 0; bool isActive = false; while(1){ if(!Midi::getMsgIfAble(&midiMsg)){ midiMsg.msgType = 0; } else { if (midiMsg.msgType == Midi::MSG_TYPE_NOTE_ON) { if(midiMsg.dataBytes[1] != 0) { oscillator.setPitch(Midi::gNotes[midiMsg.dataBytes[0]]); isActive = true; Display::writeCharacterAt('O', 1, 0); } else { isActive = false; Display::writeCharacterAt('X', 1, 0); } } else if(midiMsg.msgType == Midi::MSG_TYPE_NOTE_OFF){ isActive = false; Display::writeCharacterAt('X', 1, 0); } } if(isActive) { sample = oscillator.getNextSample(); } while(!Audio::attemptToOutputSample(sample)){}; Display::carryOutActionsUntilInterval(); } }
int main() { snd_pcm_t *pcm = nullptr; snd_rawmidi_t *nanoKEY2 = nullptr; snd_rawmidi_t *nanoKONTROL2 = nullptr; try { // open audio device // BEHRINGER UCA222 ---> http://www.behringer.com/EN/Products/UCA222.aspx if( ::snd_pcm_open( &pcm, "hw:CODEC", SND_PCM_STREAM_PLAYBACK, 0) ) { throw std::runtime_error("snd_pcm_open error"); } // set parameters if( ::snd_pcm_set_params( pcm, SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 1, // mono 44100, 0, 20*1000) ) // 20ms { throw std::runtime_error("snd_pcm_set_params error"); } // get buffer size and period size snd_pcm_uframes_t buffer_size = 0; snd_pcm_uframes_t period_size = 0; if( ::snd_pcm_get_params( pcm, &buffer_size, &period_size) ) { throw std::runtime_error("snd_pcm_get_params error"); } // allocate buffer std::vector<short> buffer(period_size); std::cout << "start (" << "buffer_size=" << buffer_size << ", " << "period_size=" << period_size << ")" << std::endl; std::cout << "MIDI:" << std::flush; // open MIDI device // KORG nanoKEY2 ---> http://www.korg.co.jp/Product/Controller/nano2/nanoKEY.html if( ::snd_rawmidi_open( &nanoKEY2, nullptr, "hw:nanoKEY2", SND_RAWMIDI_NONBLOCK ) ) { throw std::runtime_error("snd_rawmidi_open error"); } // オシレータ作成 blit_saw_oscillator oscillator(0.995, 44100); // open MIDI device // KORG nanoKONTROL2 ---> http://www.korg.co.jp/Product/Controller/nano2/nanoKONTROL.html if( ::snd_rawmidi_open( &nanoKONTROL2, nullptr, "hw:nanoKONTROL2", SND_RAWMIDI_NONBLOCK ) ) { throw std::runtime_error("snd_rawmidi_open error"); } // parameters double volume = 1.0; double cutoff = 400.0; double resonance = M_SQRT1_2; double low = 1.0; double band = 0.0; double high = 0.0; // Biquad Filter作成 biquad_filter filter(cutoff, resonance, low, band, high); do{ //-------------------- // MIDI event process //-------------------- do{ // read MIDI input std::array<unsigned char, 3> midi_data = {}; ssize_t midi_read_count = ::snd_rawmidi_read(nanoKEY2, midi_data.data(), midi_data.size()); if( midi_read_count != (int)midi_data.size() ) { // no more data break; } ::printf("\rMIDI message:0x%02x 0x%02x 0x%02x", midi_data[0], midi_data[1], midi_data[2]); ::fflush(stdout); if( midi_data[0] == 0x90/*note on*/) { oscillator.trigger(midi_data[1], midi_data[2]); } else if( midi_data[0] == 0x80/*note off*/) { oscillator.release(midi_data[1]); } }while(true); // key:control number / value:value std::map<unsigned char, unsigned char> ControlChangeMap; do{ // read MIDI input std::array<unsigned char, 3> midi_data = {}; ssize_t midi_read_count = ::snd_rawmidi_read(nanoKONTROL2, midi_data.data(), midi_data.size()); if( midi_read_count != static_cast<int>(midi_data.size()) ) { // no more data break; } ::printf("\rMIDI message:0x%02x 0x%02x 0x%02x", midi_data[0], midi_data[1], midi_data[2]); ::fflush(stdout); if( midi_data[0] == 0xb0/*control change*/){ // 最後の値のみを保持 ControlChangeMap[ midi_data[1] ] = midi_data[2]; } }while(true); // update parameters for(const auto& key_value : ControlChangeMap) { unsigned char control_number = key_value.first; double value = static_cast<double>(key_value.second)/127; if( control_number == 0x10 /* knob1 */) { volume = value; } else if( control_number == 0x11 /* knob2 */) { cutoff = 40.0*(1.0-value) + 4000.0*value; } else if( control_number == 0x12 /* knob3 */) { resonance = M_SQRT1_2*(1.0-value) + 20.0*value; } else if( control_number == 0x13 /* knob4 */) { low = value; } else if( control_number == 0x14 /* knob5 */) { band = value; } else if( control_number == 0x15 /* knob6 */) { high = value; } } // フィルタの更新が必要か? auto isFilterUpdate = [](std::pair<unsigned char, unsigned char> key_value){ unsigned char control_number = key_value.first; return control_number == 0x11 // knob2 || control_number == 0x12 // knob3 || control_number == 0x13 // knob4 || control_number == 0x14 // knob5 || control_number == 0x15;// knob6 }; if( std::any_of(ControlChangeMap.begin(), ControlChangeMap.end(), isFilterUpdate) ) { // フィルタの更新(L/R) filter.update(cutoff, resonance, low, band, high); } //--------------- // audio process //--------------- for(short& s : buffer) { s = 1000.0 * filter.process( oscillator.process() ); } //------------- // write audio //------------- if( ::snd_pcm_writei(pcm, buffer.data(), period_size) < 0 ) { throw std::runtime_error("snd_pcm_writei error"); } }while(true); std::cout << std::endl << "end" << std::endl; } catch(std::exception &ex) { std::cout << std::endl << "error:" << ex.what() << std::endl; } if(pcm != nullptr) { // close audio device ::snd_pcm_close(pcm); } if(nanoKEY2 != nullptr) { // close sound file ::snd_rawmidi_close(nanoKEY2); } if(nanoKONTROL2 != nullptr) { // close sound file ::snd_rawmidi_close(nanoKONTROL2); } return 0; }
/* * xsynth_voice_render * * generate the actual sound data for this voice */ void xsynth_voice_render(xsynth_synth_t *synth, xsynth_voice_t *voice, LADSPA_Data *out, unsigned long sample_count, int do_control_update) { unsigned long sample; synth->monophonic = *synth->monomode; synth->glide = *synth->glidemode; /* state variables saved in voice */ float lfo_pos = voice->lfo_pos, eg1 = voice->eg1, eg2 = voice->eg2; unsigned char eg1_phase = voice->eg1_phase, eg2_phase = voice->eg2_phase; int osc_index = voice->osc_index; /* temporary variables used in calculating voice */ float fund_pitch; float deltat = synth->deltat; float freq, freqkey, freqeg1, freqeg2, lfo; /* set up synthesis variables from patch */ float omega1, omega2; unsigned char osc_sync = (*(synth->osc_sync) > 0.0001f); float omega3 = *(synth->lfo_frequency); unsigned char lfo_waveform = lrintf(*(synth->lfo_waveform)); float lfo_amount_o = *(synth->lfo_amount_o); float lfo_amount_f = *(synth->lfo_amount_f); float eg1_amp = qdB_to_amplitude(velocity_to_attenuation[voice->velocity] * *(synth->eg1_vel_sens)); float eg1_rate_level[3], eg1_one_rate[3]; float eg1_amount_o = *(synth->eg1_amount_o); float eg2_amp = qdB_to_amplitude(velocity_to_attenuation[voice->velocity] * *(synth->eg2_vel_sens)); float eg2_rate_level[3], eg2_one_rate[3]; float eg2_amount_o = *(synth->eg2_amount_o); unsigned char vcf_mode = lrintf(*(synth->vcf_mode)); float qres = *(synth->vcf_qres) / 1.995f * voice->pressure; /* now 0 to 1 */ float balance1 = 1.0f - *(synth->osc_balance); float balance2 = *(synth->osc_balance); float vol_out = volume(*(synth->volume) * synth->cc_volume); fund_pitch = *(synth->glide_time) * voice->target_pitch + (1.0f - *(synth->glide_time)) * voice->prev_pitch; /* portamento */ if (do_control_update) { voice->prev_pitch = fund_pitch; /* save pitch for next time */ } fund_pitch *= synth->pitch_bend * *(synth->tuning); omega1 = *(synth->osc1_pitch) * fund_pitch; omega2 = *(synth->osc2_pitch) * fund_pitch; eg1_rate_level[0] = *(synth->eg1_attack_time) * eg1_amp; /* eg1_attack_time * 1.0f * eg1_amp */ eg1_one_rate[0] = 1.0f - *(synth->eg1_attack_time); eg1_rate_level[1] = *(synth->eg1_decay_time) * *(synth->eg1_sustain_level) * eg1_amp; eg1_one_rate[1] = 1.0f - *(synth->eg1_decay_time); eg1_rate_level[2] = 0.0f; /* eg1_release_time * 0.0f * eg1_amp */ eg1_one_rate[2] = 1.0f - *(synth->eg1_release_time); eg2_rate_level[0] = *(synth->eg2_attack_time) * eg2_amp; eg2_one_rate[0] = 1.0f - *(synth->eg2_attack_time); eg2_rate_level[1] = *(synth->eg2_decay_time) * *(synth->eg2_sustain_level) * eg2_amp; eg2_one_rate[1] = 1.0f - *(synth->eg2_decay_time); eg2_rate_level[2] = 0.0f; eg2_one_rate[2] = 1.0f - *(synth->eg2_release_time); eg1_amp *= 0.99f; /* Xsynth's original eg phase 1 to 2 transition check was: */ eg2_amp *= 0.99f; /* if (!eg1_phase && eg1 > 0.99f) eg1_phase = 1; */ freq = M_PI_F * deltat * fund_pitch * synth->mod_wheel; /* now (0 to 1) * pi */ freqkey = freq * *(synth->vcf_cutoff); freqeg1 = freq * *(synth->eg1_amount_f); freqeg2 = freq * *(synth->eg2_amount_f); /* copy some things so oscillator functions can see them */ voice->osc1.waveform = lrintf(*(synth->osc1_waveform)); voice->osc1.pw = *(synth->osc1_pulsewidth); voice->osc2.waveform = lrintf(*(synth->osc2_waveform)); voice->osc2.pw = *(synth->osc2_pulsewidth); /* --- LFO, EG1, and EG2 section */ for (sample = 0; sample < sample_count; sample++) { lfo = oscillator(&lfo_pos, omega3, deltat, lfo_waveform); eg1 = eg1_rate_level[eg1_phase] + eg1_one_rate[eg1_phase] * eg1; eg2 = eg2_rate_level[eg2_phase] + eg2_one_rate[eg2_phase] * eg2; voice->osc2_w_buf[sample] = deltat * omega2 * (1.0f + eg1 * eg1_amount_o) * (1.0f + eg2 * eg2_amount_o) * (1.0f + lfo * lfo_amount_o); voice->freqcut_buf[sample] = (freqkey + freqeg1 * eg1 + freqeg2 * eg2) * (1.0f + lfo * lfo_amount_f); voice->vca_buf[sample] = eg1 * vol_out; if (!eg1_phase && eg1 > eg1_amp) eg1_phase = 1; /* flip from attack to decay */ if (!eg2_phase && eg2 > eg2_amp) eg2_phase = 1; /* flip from attack to decay */ } /* --- VCO 1 section */ if (osc_sync) blosc_master(sample_count, voice, &voice->osc1, osc_index, balance1, deltat * omega1); else blosc_single1(sample_count, voice, &voice->osc1, osc_index, balance1, deltat * omega1); /* --- VCO 2 section */ if (osc_sync) blosc_slave(sample_count, voice, &voice->osc2, osc_index, balance2, voice->osc2_w_buf); else blosc_single2(sample_count, voice, &voice->osc2, osc_index, balance2, voice->osc2_w_buf); /* --- VCF and VCA section */ switch (vcf_mode) { default: case 0: vcf_2pole(voice, sample_count, voice->osc_audio + osc_index, out, voice->freqcut_buf, qres, voice->vca_buf); break; case 1: vcf_4pole(voice, sample_count, voice->osc_audio + osc_index, out, voice->freqcut_buf, qres, voice->vca_buf); break; case 2: vcf_mvclpf(voice, sample_count, voice->osc_audio + osc_index, out, voice->freqcut_buf, qres, voice->vca_buf); break; } osc_index += sample_count; if (do_control_update) { /* do those things should be done only once per control-calculation * interval ("nugget"), such as voice check-for-dead, pitch envelope * calculations, volume envelope phase transition checks, etc. */ /* check if we've decayed to nothing, turn off voice if so */ if (eg1_phase == 2 && voice->vca_buf[sample_count - 1] < 6.26e-6f) { /* sound has completed its release phase (>96dB below volume '5' max) */ XDB_MESSAGE(XDB_NOTE, " xsynth_voice_render check for dead: killing note id %d\n", voice->note_id); xsynth_voice_off(voice); return; /* we're dead now, so return */ } /* already saved prev_pitch above */ /* check oscillator audio buffer index, shift buffer if necessary */ if (osc_index > MINBLEP_BUFFER_LENGTH - (XSYNTH_NUGGET_SIZE + LONGEST_DD_PULSE_LENGTH)) { memcpy(voice->osc_audio, voice->osc_audio + osc_index, LONGEST_DD_PULSE_LENGTH * sizeof (float)); memset(voice->osc_audio + LONGEST_DD_PULSE_LENGTH, 0, (MINBLEP_BUFFER_LENGTH - LONGEST_DD_PULSE_LENGTH) * sizeof (float)); osc_index = 0; } } /* save things for next time around */ voice->lfo_pos = lfo_pos; voice->eg1 = eg1; voice->eg1_phase = eg1_phase; voice->eg2 = eg2; voice->eg2_phase = eg2_phase; voice->osc_index = osc_index; }