Exemplo n.º 1
0
void OCPiano::PressKey(const int Pitch, const bool Poly, const bool Tied)
{
    emit NoteOn(Pitch);
    int NoteType=tsnote;
    if (Tied) NoteType=tstiednote;
    if (Poly)
    {
        Types.append(NoteType+2);
        Pitches.append(Pitch);
        CurrentPitch=0;
    }
    else
    {
        Types.append(NoteType);
        Pitches.append(Pitch);
        CurrentPitch=Pitch;
        QList<QPair<int,int> >Notes;
        for (int i=0;i<Pitches.count();i++)
        {
            Notes.append(qMakePair(Pitches[i],Types[i]));
        }
        emit TriggerNotes(Notes);
        for (int i=0;i<Pitches.count()-1;i++)
        {
            emit NoteOff(Pitches[i]);
        }
        Pitches.clear();
        Types.clear();
    }
}
Exemplo n.º 2
0
void Fl_MIDIKeyboard::press_key(uchar k) {
    if (!pressed_keys[k]) {

        NoteOn(k);                          // play the key with the MIDI driver

        pressed_keys[k] = true;             // adjust the pressed status variables
        _npressed++;
        if (_npressed == 1) _maxpressed = _minpressed = k;
        else if (k > _maxpressed) _maxpressed = k;
        else if (k < _minpressed) _minpressed = k;
        redraw();
        if (when() & MKB_WHEN_PRESS) {
            _callback_status = MKB_PRESS | k;
            do_callback();                  // if needed, calls the callback
        }
        //cout << "Pressed " << (char)k << " npressed = " << (int)_npressed << endl;
    }
}
Exemplo n.º 3
0
void 
BMidiLocalConsumer::Data(uchar* data, size_t length, bool atomic, bigtime_t time)
{
	if (atomic) {
		switch (data[0] & 0xF0) {
			case B_NOTE_OFF:
			{
				if (length == 3)
					NoteOff(data[0] & 0x0F, data[1], data[2], time);
				break;
			}

			case B_NOTE_ON:
			{
				if (length == 3)
					NoteOn(data[0] & 0x0F, data[1], data[2], time);
				break;
			}

			case B_KEY_PRESSURE:
			{
				if (length == 3)
					KeyPressure(data[0] & 0x0F, data[1], data[2], time);
				break;
			}

			case B_CONTROL_CHANGE:
			{
				if (length == 3)
					ControlChange(data[0] & 0x0F, data[1], data[2], time);
				break;
			}

			case B_PROGRAM_CHANGE:
			{
				if (length == 2)
					ProgramChange(data[0] & 0x0F, data[1], time);
				break;
			}

			case B_CHANNEL_PRESSURE:
			{
				if (length == 2)
					ChannelPressure(data[0] & 0x0F, data[1], time);
				break;
			}

			case B_PITCH_BEND:
			{
				if (length == 3)
					PitchBend(data[0] & 0x0F, data[1], data[2], time);
				break;
			}

			case 0xF0:
			{
				switch (data[0]) {
					case B_SYS_EX_START:
					{
						if (data[length - 1] == B_SYS_EX_END) {
							SystemExclusive(data + 1, length - 2, time);
						} else { // sysex-end is not required
							SystemExclusive(data + 1, length - 1, time);
						}
						break;
					}

					case B_TUNE_REQUEST:
					case B_SYS_EX_END:
					{
						if (length == 1) {
							SystemCommon(data[0], 0, 0, time);
						}
						break;
					}

					case B_CABLE_MESSAGE:
					case B_MIDI_TIME_CODE:
					case B_SONG_SELECT:
					{
						if (length == 2) {
							SystemCommon(data[0], data[1], 0, time);
						}
						break;
					}

					case B_SONG_POSITION:
					{
						if (length == 3) {
							SystemCommon(data[0], data[1], data[2], time);
						}
						break;
					}
	
					case B_TIMING_CLOCK:
					case B_START:
					case B_CONTINUE:
					case B_STOP:
					case B_ACTIVE_SENSING:
					{
						if (length == 1) {
							SystemRealTime(data[0], time);
						}
						break;
					}

					case B_SYSTEM_RESET:
					{
						if (length == 1) {
							SystemRealTime(data[0], time);
						} else if ((length == 6) && (data[1] == 0x51) 
								&& (data[2] == 0x03)) {
							int32 tempo = 
								(data[3] << 16) | (data[4] << 8) | data[5];

							TempoChange(60000000/tempo, time);
						}
					}
				}
				break;
			}
		}
	}
}
Exemplo n.º 4
0
//--------------------------------------------------------------
void AppCore::setup(const int numOutChannels, const int numInChannels,
				    const int sampleRate, const int ticksPerBuffer) {

	ofSetFrameRate(60);
	ofSetVerticalSync(true);
	//ofSetLogLevel(OF_LOG_VERBOSE);
	
	// double check where we are ...
	cout << ofFilePath::getCurrentWorkingDirectory() << endl;
	
	if(!pd.init(numOutChannels, numInChannels, sampleRate, ticksPerBuffer)) {
		ofLog(OF_LOG_ERROR, "Could not init pd");
		OF_EXIT_APP(1);
	}
    
    midiChan = 1; // midi channels are 1-16
	
	// subscribe to receive source names
	pd.subscribe("toOF");
	pd.subscribe("env");

	// add message receiver, disables polling (see processEvents)
	pd.addReceiver(*this);   // automatically receives from all subscribed sources
	pd.ignore(*this, "env"); // don't receive from "env"
    //pd.ignore(*this);             // ignore all sources
	//pd.receive(*this, "toOF");	// receive only from "toOF"
	
    // add midi receiver
    pd.addMidiReceiver(*this);  // automatically receives from all channels
    //pd.ignoreMidi(*this, 1);     // ignore midi channel 1
    //pd.ignoreMidi(*this);        // ignore all channels
    //pd.receiveMidi(*this, 1);    // receive only from channel 1

	// add the data/pd folder to the search path
	pd.addToSearchPath("pd");

	// audio processing on
	pd.start();

	
	cout << endl << "BEGIN Patch Test" << endl;
	
	// open patch
	Patch patch = pd.openPatch("test.pd");
	cout << patch << endl;
	
	// close patch
	pd.closePatch(patch);
	cout << patch << endl;
	
	// open patch
	patch = pd.openPatch("test.pd");
	cout << patch << endl;
	
	cout << "FINISH Patch Test" << endl;
	
	
	cout << endl << "BEGIN Message Test" << endl;
	
	// test basic atoms
	pd.sendBang("fromOF");
	pd.sendFloat("fromOF", 100);
	pd.sendSymbol("fromOF", "test string");
    
    // stream interface
    pd << Bang("fromOF")
       << Float("fromOF", 100)
       << Symbol("fromOF", "test string");
	
	// send a list
	pd.startMessage();
		pd.addFloat(1.23);
		pd.addSymbol("a symbol");
	pd.finishList("fromOF");
	
	// send a message to the $0 receiver ie $0-toOF
	pd.startMessage();
		pd.addFloat(1.23);
		pd.addSymbol("a symbol");
	pd.finishList(patch.dollarZeroStr()+"-fromOF");
	
    // send a list using the List object
    List testList;
    testList.addFloat(1.23);
    testList.addSymbol("sent from a List object");
    pd.sendList("fromOF", testList);
    pd.sendMessage("fromOF", "msg", testList);
    
    // stream interface for list
    pd << StartMessage() << 1.23 << "sent from a streamed list" << FinishList("fromOF");
    
	cout << "FINISH Message Test" << endl;
	
	
	cout << endl << "BEGIN MIDI Test" << endl;
	
	// send functions
	pd.sendNoteOn(midiChan, 60);
	pd.sendControlChange(midiChan, 0, 64);
	pd.sendProgramChange(midiChan, 100);    // note: pgm num range is 1 - 128
	pd.sendPitchBend(midiChan, 2000);   // note: ofxPd uses -8192 - 8192 while [bendin] returns 0 - 16383,
                                        // so sending a val of 2000 gives 10192 in pd
	pd.sendAftertouch(midiChan, 100);
	pd.sendPolyAftertouch(midiChan, 64, 100);
	pd.sendMidiByte(0, 239);    // note: pd adds +2 to the port number from [midiin], [sysexin], & [realtimein]
	pd.sendSysex(0, 239);       // so sending to port 0 gives port 2 in pd
	pd.sendSysRealTime(0, 239);
	
	// stream
	pd << NoteOn(midiChan, 60) << ControlChange(midiChan, 100, 64)
       << ProgramChange(midiChan, 100) << PitchBend(midiChan, 2000)
       << Aftertouch(midiChan, 100) << PolyAftertouch(midiChan, 64, 100)
	   << StartMidi(0) << 239 << Finish()
	   << StartSysex(0) << 239 << Finish()
	   << StartSysRealTime(0) << 239 << Finish();
    
	cout << "FINISH MIDI Test" << endl;
	
	
	cout << endl << "BEGIN Array Test" << endl;
	
	// array check length
	cout << "array1 len: " << pd.arraySize("array1") << endl;
	
	// read array
	std::vector<float> array1;
	pd.readArray("array1", array1);	// sets array to correct size
	cout << "array1 ";
	for(int i = 0; i < array1.size(); ++i)
		cout << array1[i] << " ";
	cout << endl;
	
	// write array
	for(int i = 0; i < array1.size(); ++i)
		array1[i] = i;
	pd.writeArray("array1", array1);
	
	// ready array
	pd.readArray("array1", array1);
	cout << "array1 ";
	for(int i = 0; i < array1.size(); ++i)
		cout << array1[i] << " ";
	cout << endl;
	
	// clear array
	pd.clearArray("array1", 10);
	
	// ready array
	pd.readArray("array1", array1);
	cout << "array1 ";
	for(int i = 0; i < array1.size(); ++i)
		cout << array1[i] << " ";
	cout << endl;

	cout << "FINISH Array Test" << endl;


	
	cout << endl << "BEGIN PD Test" << endl;
	pd.sendSymbol("fromOF", "test");
	cout << "FINISH PD Test" << endl << endl;
	
	
	cout << endl << "BEGIN Event Polling Test" << endl;
	
	// clear receivers, enable polling
	pd.clearReceivers();
    pd.clearMidiReceivers();
	
	pd.sendSymbol("fromOF", "test");
	processEvents(); // <-- manually poll for events
	
	// re-add receivers, disable polling
	pd.addReceiver(*this);
    pd.addMidiReceiver(*this);
	pd.ignore(*this, "env");
	
	cout << "FINISH Event Polling Test" << endl << endl;
	
	
	// play a tone by sending a list
	// [list tone pitch 72 (
	pd.startMessage();
		pd.addSymbol("pitch");
		pd.addFloat(72);
	pd.finishList("tone");
	pd.sendBang("tone");

}
Exemplo n.º 5
0
void AliveAudio::NoteOn(int program, int note, char velocity, int trackID, float trackDelay)
{
	NoteOn(program, note, velocity, 0, trackID, trackDelay);
}
Exemplo n.º 6
0
void __cdecl main(int argc, char **argv)
{
	HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	int running = 1;

#ifdef WIN32
	if (IsDebuggerPresent())
	{
		// turn on floating-point exceptions
		unsigned int prev;
		_clearfp();
		_controlfp_s(&prev, 0, _EM_ZERODIVIDE|_EM_INVALID);
	}
#endif

	// check the correct BASS was loaded
	if (HIWORD(BASS_GetVersion()) != BASSVERSION)
	{
		fprintf(stderr, "An incorrect version of BASS.DLL was loaded");
		return;
	}

	// set the window title
	SetConsoleTitle(TEXT(title_text));

	// set the console buffer size
	static const COORD bufferSize = { 80, 50 };
	SetConsoleScreenBufferSize(hOut, bufferSize);

	// set the console window size
	static const SMALL_RECT windowSize = { 0, 0, 79, 49 };
	SetConsoleWindowInfo(hOut, TRUE, &windowSize);

	// clear the window
	Clear(hOut);

	// hide the cursor
	static const CONSOLE_CURSOR_INFO cursorInfo = { 100, FALSE };
	SetConsoleCursorInfo(hOut, &cursorInfo);

	// set input mode
	SetConsoleMode(hIn, 0);

	// 10ms update period
	const DWORD STREAM_UPDATE_PERIOD = 10;
	BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, STREAM_UPDATE_PERIOD);

	// initialize BASS sound library
	const DWORD STREAM_FREQUENCY = 48000;
	if (!BASS_Init(-1, STREAM_FREQUENCY, BASS_DEVICE_LATENCY, 0, NULL))
		Error("Can't initialize device");

	// get device info
	BASS_GetInfo(&info);

	// if the device's output rate is unknown default to stream frequency
	if (!info.freq) info.freq = STREAM_FREQUENCY;

	// debug print info
	DebugPrint("frequency: %d (min %d, max %d)\n", info.freq, info.minrate, info.maxrate);
	DebugPrint("device latency: %dms\n", info.latency);
	DebugPrint("device minbuf: %dms\n", info.minbuf);
	DebugPrint("ds version: %d (effects %s)\n", info.dsver, info.dsver < 8 ? "disabled" : "enabled");

	// default buffer size = update period + 'minbuf' + 1ms extra margin
	BASS_SetConfig(BASS_CONFIG_BUFFER, STREAM_UPDATE_PERIOD + info.minbuf + 1);
	DebugPrint("using a %dms buffer\r", BASS_GetConfig(BASS_CONFIG_BUFFER));

	// create a stream, stereo so that effects sound nice
	stream = BASS_StreamCreate(info.freq, 2, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream, 0);

	// set channel to apply effects
	fx_channel = stream;

#ifdef BANDLIMITED_SAWTOOTH
	// initialize bandlimited sawtooth tables
	InitSawtooth();
#endif

	// initialize waves
	InitWave();

	// enable the first oscillator
	osc_config[0].enable = true;

	// reset all controllers
	Control::ResetAll();

	// start playing the audio stream
	BASS_ChannelPlay(stream, FALSE);

	// get the number of midi devices
	UINT midiInDevs = Midi::Input::GetNumDevices();
	DebugPrint("MIDI input devices: %d\n", midiInDevs);

	// print device names
	for (UINT i = 0; i < midiInDevs; ++i)
	{
		MIDIINCAPS midiInCaps;
		if (Midi::Input::GetDeviceCaps(i, midiInCaps) == 0)
		{
			DebugPrint("%d: %s\n", i, midiInCaps.szPname);
		}
	}

	// if there are any devices available...
	if (midiInDevs > 0)
	{
		// open and start midi input
		// TO DO: select device number via a configuration setting
		Midi::Input::Open(0);
		Midi::Input::Start();
	}

	// initialize to middle c
	note_most_recent = 60;
	voice_note[voice_most_recent] = unsigned char(note_most_recent);

	DisplaySpectrumAnalyzer displaySpectrumAnalyzer;
	DisplayKeyVolumeEnvelope displayKeyVolumeEnvelope;
	DisplayOscillatorWaveform displayOscillatorWaveform;
	DisplayOscillatorFrequency displayOscillatorFrequency;
	DisplayLowFrequencyOscillator displayLowFrequencyOscillator;
	DisplayFilterFrequency displayFilterFrequency;

	// initialize spectrum analyzer
	displaySpectrumAnalyzer.Init(stream, info);

	// initialize key display
	displayKeyVolumeEnvelope.Init(hOut);

	// show output scale and key octave
	PrintOutputScale(hOut);
	PrintKeyOctave(hOut);
	PrintGoToEffects(hOut);
	PrintAntialias(hOut);

	// show main page
	Menu::SetActivePage(hOut, Menu::PAGE_MAIN);

	while (running)
	{
		// if there are any pending input events...
		DWORD numEvents = 0;
		while (GetNumberOfConsoleInputEvents(hIn, &numEvents) && numEvents > 0)
		{
			// get the next input event
			INPUT_RECORD keyin;
			ReadConsoleInput(hIn, &keyin, 1, &numEvents);
			if (keyin.EventType == KEY_EVENT)
			{
				// handle interface keys
				if (keyin.Event.KeyEvent.bKeyDown)
				{
					WORD code = keyin.Event.KeyEvent.wVirtualKeyCode;
					DWORD modifiers = keyin.Event.KeyEvent.dwControlKeyState;
					if (code == VK_ESCAPE)
					{
						running = 0;
						break;
					}
					else if (code == VK_OEM_MINUS || code == VK_SUBTRACT)
					{
						Menu::UpdatePercentageProperty(output_scale, -1, modifiers, 0, 4);
						PrintOutputScale(hOut);
					}
					else if (code == VK_OEM_PLUS || code == VK_ADD)
					{
						Menu::UpdatePercentageProperty(output_scale, +1, modifiers, 0, 4);
						PrintOutputScale(hOut);
					}
					else if (code == VK_OEM_4)	// '['
					{
						if (keyboard_octave > 1)
						{
							for (int k = 0; k < KEYS; ++k)
							{
								if (key_down[k])
									NoteOff(k + keyboard_octave * 12);
							}
							--keyboard_octave;
							for (int k = 0; k < KEYS; ++k)
							{
								if (key_down[k])
									NoteOn(k + keyboard_octave * 12);
							}
							PrintKeyOctave(hOut);
						}
					}
					else if (code == VK_OEM_6)	// ']'
					{
						if (keyboard_octave < 9)
						{
							for (int k = 0; k < KEYS; ++k)
							{
								if (key_down[k])
									NoteOff(k + keyboard_octave * 12);
							}
							++keyboard_octave;
							for (int k = 0; k < KEYS; ++k)
							{
								if (key_down[k])
									NoteOn(k + keyboard_octave * 12);
							}
							PrintKeyOctave(hOut);
						}
					}
					else if (code == VK_F12)
					{
						use_antialias = !use_antialias;
						PrintAntialias(hOut);
					}
					else if (code >= VK_F1 && code < VK_F10)
					{
						Menu::SetActiveMenu(hOut, code - VK_F1);
					}
					else if (code == VK_F10)
					{
						PrintGoToEffects(hOut);
						Menu::SetActivePage(hOut, Menu::PAGE_MAIN);
					}
					else if (code == VK_F11)
					{
						PrintGoToMain(hOut);
						Menu::SetActivePage(hOut, Menu::PAGE_FX);
					}
					else if (code == VK_TAB)
					{
						if (modifiers & SHIFT_PRESSED)
							Menu::PrevMenu(hOut);
						else
							Menu::NextMenu(hOut);
					}
					else if (code == VK_UP || code == VK_DOWN || code == VK_RIGHT || code == VK_LEFT)
					{
						Menu::Handler(hOut, code, modifiers);
					}
				}

				// handle note keys
				for (int k = 0; k < KEYS; k++)
				{
					if (keyin.Event.KeyEvent.wVirtualKeyCode == keys[k])
					{
						// key down
						bool down = (keyin.Event.KeyEvent.bKeyDown != 0);

						// if key down state changed...
						if (key_down[k] != down)
						{
							// update state
							key_down[k] = down;

							// if pressing the key
							if (down)
							{
								// note on
								NoteOn(k + keyboard_octave * 12);
							}
							else
							{
								// note off
								NoteOff(k + keyboard_octave * 12);
							}
						}
						break;
					}
				}
			}
		}

		// center frequency of the zeroth semitone band
		// (one octave down from the lowest key)
		float const freq_min = powf(2, float(keyboard_octave - 6)) * middle_c_frequency;

		// update the spectrum analyzer display
		displaySpectrumAnalyzer.Update(hOut, stream, info, freq_min);

		// update note key volume envelope display
		displayKeyVolumeEnvelope.Update(hOut);

		if (Menu::active_page == Menu::PAGE_MAIN)
		{
			// update the oscillator waveform display
			displayOscillatorWaveform.Update(hOut, info, voice_most_recent);

			// update the oscillator frequency displays
			for (int o = 0; o < NUM_OSCILLATORS; ++o)
			{
				if (osc_config[o].enable)
					displayOscillatorFrequency.Update(hOut, voice_most_recent, o);
			}

			// update the low-frequency oscillator display
			displayLowFrequencyOscillator.Update(hOut);

			// update the filter frequency display
			if (flt_config.enable)
				displayFilterFrequency.Update(hOut, voice_most_recent);
		}

		// show CPU usage
		PrintConsole(hOut, { 73, 49 }, "%6.2f%%", BASS_GetCPU());

		// sleep for 1/60th of second
		Sleep(16);
	}

	if (midiInDevs)
	{
		// stop and close midi input
		Midi::Input::Stop();
		Midi::Input::Close();
	}

	// clean up spectrum analyzer
	displaySpectrumAnalyzer.Cleanup(stream);

	// clear the window
	Clear(hOut);

	BASS_Free();
}
Exemplo n.º 7
0
int Ims::PlayEvent(void)
{
	static unsigned char stCode;
	unsigned char curCode;
	int delay, delayTime = 0;
	int voice, note, volume, index;
	int *paramArray;
	unsigned short int pitchBend;
    int instIndexInBnk;

again:
	curCode = m_ims->songData[m_songDataIndex];

	//fflush(stdout);
	//return (nElapsed * MAX_SLIDER_PROGRESS / m_cbImsDataSize);

	// 0x7F == 127
	if (curCode > 0x7F) 
	{	
		m_songDataIndex++;
		stCode = curCode;
	} 
	else 
		curCode = stCode;

	voice = curCode & 0x0F;	// 오른쪽 4비트를 얻는다 (채널 번호)

	// 왼쪽 4비트에 이벤트 종류가 저장되어 있다
	switch (curCode & 0xF0) 
	{	
		case 0x80: // note off
			note = m_ims->songData[m_songDataIndex];
			volume = m_ims->songData[m_songDataIndex + 1];

			NoteOff(voice);						
			SetVoiceVolume(voice, volume);
			NoteOn(voice, note);
			m_songDataIndex += 2;
			break;

		case 0x90: // note on
			note = m_ims->songData[m_songDataIndex];
			volume = m_ims->songData[m_songDataIndex + 1];

			NoteOff(voice);
			if (volume) {
				SetVoiceVolume(voice, volume);
				NoteOn(voice, note);
			}
			m_songDataIndex += 2;
			break;

		case 0xA0: // Set volume
			volume = m_ims->songData[m_songDataIndex];
			SetVoiceVolume(voice, volume);
			m_songDataIndex++;
			break;

		case 0xC0: // Set Instrument
			index = m_ims->songData[m_songDataIndex];
			instIndexInBnk = m_ims->instIndex[index].index;

			// 악기가 있다면..
			if ( instIndexInBnk >= 0 && 
					instIndexInBnk < m_ims->m_bnk->header.totalEntry)
			{
				paramArray = 
					&m_ims->m_bnk->instRecord32[instIndexInBnk].op1.keyScaleLevel;
				SetVoiceTimbre(voice, paramArray);
			}
			else
			{
				/*
				printf("%d/%d\n", instIndexInBnk, 
						m_ims->m_bnk->header.totalEntry);
				fflush(stdout);
				*/
			}

			m_songDataIndex++;
			break;

		case 0xE0: // Set Pitch
			memcpy(&pitchBend, &m_ims->songData[m_songDataIndex], 
					sizeof(unsigned short int));
			pitchBend = pitchBend / 2;

			SetVoicePitch(voice, pitchBend);
			m_songDataIndex += sizeof(unsigned short int);
			break;

		case 0xF0: // Set Tempo
			m_songDataIndex += 2;
			m_basicTempo = (m_ims->header.nBasicTempo * 
					m_ims->songData[m_songDataIndex]);
			m_basicTempo += m_ims->header.nBasicTempo * 
				m_ims->songData[m_songDataIndex + 1] / 128;
			m_songDataIndex += 3;
			break;
	}

	while (1) 
	{
		delay = m_ims->songData[m_songDataIndex];
		m_songDataIndex++;

		// IMS finish code
		if (m_ims->songData[m_songDataIndex] == 0xFC) 
		{
			if ( m_repeatMode == REPEAT_THIS )
			{
				Rewind();
			}
			else
			{
				m_playMode=SONG_END;
				break;
			}

            delayTime += delay;
        	return delayTime;
        }

		if (delay == 0xF8) 
			delayTime += 240;
		else 
			break;
	}

	delayTime += delay;

	if (delayTime == 0) 
		goto again;
	else 
		m_tick += delayTime;

	return delayTime;
}
Exemplo n.º 8
0
//--------------------------------------------------------------
void ofApp::setup() {

	ofSetFrameRate(60);
	ofSetVerticalSync(true);
	//ofSetLogLevel("Pd", OF_LOG_VERBOSE); // see verbose info inside

	// double check where we are ...
	cout << ofFilePath::getCurrentWorkingDirectory() << endl;

	// the number of libpd ticks per buffer,
	// used to compute the audio buffer len: tpb * blocksize (always 64)
	#ifdef TARGET_LINUX_ARM
		// longer latency for Raspberry PI
		int ticksPerBuffer = 32; // 32 * 64 = buffer len of 2048
		int numInputs = 0; // no built in mic
	#else
		int ticksPerBuffer = 8; // 8 * 64 = buffer len of 512
		int numInputs = 1;
	#endif

	// setup OF sound stream
	ofSoundStreamSetup(2, numInputs, this, 44100, ofxPd::blockSize()*ticksPerBuffer, 3);

	// setup Pd
	//
	// set 4th arg to true for queued message passing using an internal ringbuffer,
	// this is useful if you need to control where and when the message callbacks
	// happen (ie. within a GUI thread)
	//
	// note: you won't see any message prints until update() is called since
	// the queued messages are processed there, this is normal
	//
	if(!pd.init(2, numInputs, 44100, ticksPerBuffer, false)) {
		OF_EXIT_APP(1);
	}

	midiChan = 1; // midi channels are 1-16

	// subscribe to receive source names
	pd.subscribe("toOF");
	pd.subscribe("env");

	// add message receiver, required if you want to recieve messages
	pd.addReceiver(*this); // automatically receives from all subscribed sources
	pd.ignoreSource(*this, "env");        // don't receive from "env"
	//pd.ignoreSource(*this);             // ignore all sources
	//pd.receiveSource(*this, "toOF");	  // receive only from "toOF"

	// add midi receiver, required if you want to recieve midi messages
	pd.addMidiReceiver(*this); // automatically receives from all channels
	//pd.ignoreMidiChannel(*this, 1);     // ignore midi channel 1
	//pd.ignoreMidiChannel(*this);        // ignore all channels
	//pd.receiveMidiChannel(*this, 1);    // receive only from channel 1

	// add the data/pd folder to the search path
	pd.addToSearchPath("pd/abs");

	// audio processing on
	pd.start();

	// -----------------------------------------------------
	cout << endl << "BEGIN Patch Test" << endl;

	// open patch
	Patch patch = pd.openPatch("pd/test.pd");
	cout << patch << endl;

	// close patch
	pd.closePatch(patch);
	cout << patch << endl;

	// open patch again
	patch = pd.openPatch(patch);
	cout << patch << endl;
	
	cout << "FINISH Patch Test" << endl;

	// -----------------------------------------------------
	cout << endl << "BEGIN Message Test" << endl;

	// test basic atoms
	pd.sendBang("fromOF");
	pd.sendFloat("fromOF", 100);
	pd.sendSymbol("fromOF", "test string");

	// stream interface
	pd << Bang("fromOF")
	   << Float("fromOF", 100)
	   << Symbol("fromOF", "test string");

	// send a list
	pd.startMessage();
	pd.addFloat(1.23);
	pd.addSymbol("a symbol");
	pd.finishList("fromOF");

	// send a message to the $0 receiver ie $0-fromOF
	pd.startMessage();
	pd.addFloat(1.23);
	pd.addSymbol("a symbol");
	pd.finishList(patch.dollarZeroStr()+"-fromOF");

	// send a list using the List object
	List testList;
	testList.addFloat(1.23);
	testList.addSymbol("sent from a List object");
	pd.sendList("fromOF", testList);
	pd.sendMessage("fromOF", "msg", testList);

	// stream interface for list
	pd << StartMessage() << 1.23 << "sent from a streamed list" << FinishList("fromOF");

	cout << "FINISH Message Test" << endl;

	// -----------------------------------------------------
	cout << endl << "BEGIN MIDI Test" << endl;

	// send functions
	pd.sendNoteOn(midiChan, 60);
	pd.sendControlChange(midiChan, 0, 64);
	pd.sendProgramChange(midiChan, 100);    // note: pgm num range is 1 - 128
	pd.sendPitchBend(midiChan, 2000);   // note: ofxPd uses -8192 - 8192 while [bendin] returns 0 - 16383,
										// so sending a val of 2000 gives 10192 in pd
	pd.sendAftertouch(midiChan, 100);
	pd.sendPolyAftertouch(midiChan, 64, 100);
	pd.sendMidiByte(0, 239);    // note: pd adds +2 to the port number from [midiin], [sysexin], & [realtimein]
	pd.sendSysex(0, 239);       // so sending to port 0 gives port 2 in pd
	pd.sendSysRealTime(0, 239);

	// stream
	pd << NoteOn(midiChan, 60) << ControlChange(midiChan, 100, 64)
	   << ProgramChange(midiChan, 100) << PitchBend(midiChan, 2000)
	   << Aftertouch(midiChan, 100) << PolyAftertouch(midiChan, 64, 100)
	   << StartMidi(0) << 239 << Finish()
	   << StartSysex(0) << 239 << Finish()
	   << StartSysRealTime(0) << 239 << Finish();

	cout << "FINISH MIDI Test" << endl;

	// -----------------------------------------------------
	cout << endl << "BEGIN Array Test" << endl;

	// array check length
	cout << "array1 len: " << pd.arraySize("array1") << endl;

	// read array
	std::vector<float> array1;
	pd.readArray("array1", array1);	// sets array to correct size
	cout << "array1 ";
	for(int i = 0; i < array1.size(); ++i)
		cout << array1[i] << " ";
	cout << endl;

	// write array
	for(int i = 0; i < array1.size(); ++i)
		array1[i] = i;
	pd.writeArray("array1", array1);

	// ready array
	pd.readArray("array1", array1);
	cout << "array1 ";
	for(int i = 0; i < array1.size(); ++i)
		cout << array1[i] << " ";
	cout << endl;

	// clear array
	pd.clearArray("array1", 10);

	// ready array
	pd.readArray("array1", array1);
	cout << "array1 ";
	for(int i = 0; i < array1.size(); ++i)
		cout << array1[i] << " ";
	cout << endl;

	cout << "FINISH Array Test" << endl;

	// -----------------------------------------------------
	cout << endl << "BEGIN PD Test" << endl;

	pd.sendSymbol("fromOF", "test");

	cout << "FINISH PD Test" << endl << endl;

	// -----------------------------------------------------
	cout << endl << "BEGIN Instance Test" << endl;

	// open 10 instances
	for(int i = 0; i < 10; ++i) {
		Patch p = pd.openPatch("pd/instance.pd");
		instances.push_back(p);
	}

	// send a hello bang to each instance individually using the dollarZero
	// to [r $0-instance] which should print the instance dollarZero unique id
	// and a unique random number
	for(int i = 0; i < instances.size(); ++i) {
		pd.sendBang(instances[i].dollarZeroStr()+"-instance");
	}

	// send a random float between 0 and 100
	for(int i = 0; i < instances.size(); ++i) {
		pd.sendFloat(instances[i].dollarZeroStr()+"-instance", int(ofRandom(0, 100)));
	}

	// send a symbol
	for(int i = 0; i < instances.size(); ++i) {
		pd.sendSymbol(instances[i].dollarZeroStr()+"-instance", "howdy dude");
	}

	// close all instances
	for(int i = 0; i < instances.size(); ++i) {
		pd.closePatch(instances[i]);
	}
	instances.clear();

	cout << "FINISH Instance Test" << endl;

	// -----------------------------------------------------
	// play a tone by sending a list
	// [list tone pitch 72 (
	pd.startMessage();
	pd.addSymbol("pitch");
	pd.addFloat(72);
	pd.finishList("tone");
	pd.sendBang("tone");
}