├── .gitignore ├── ABOUT-NLS ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── cJSON ├── LICENSE ├── Makefile.am ├── cJSON.c └── cJSON.h ├── configure.ac ├── doc ├── .gitignore ├── Makefile.am ├── cursynth.texi └── fdl.texi ├── mopo ├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── configure.ac └── src │ ├── Makefile.am │ ├── delay.cpp │ ├── delay.h │ ├── envelope.cpp │ ├── envelope.h │ ├── feedback.cpp │ ├── feedback.h │ ├── filter.cpp │ ├── filter.h │ ├── linear_slope.cpp │ ├── linear_slope.h │ ├── memory.h │ ├── midi_lookup.cpp │ ├── midi_lookup.h │ ├── mono_panner.cpp │ ├── mono_panner.h │ ├── mopo.h │ ├── operators.cpp │ ├── operators.h │ ├── oscillator.cpp │ ├── oscillator.h │ ├── processor.cpp │ ├── processor.h │ ├── processor_router.cpp │ ├── processor_router.h │ ├── send_receive.cpp │ ├── send_receive.h │ ├── smooth_filter.cpp │ ├── smooth_filter.h │ ├── smooth_value.cpp │ ├── smooth_value.h │ ├── step_generator.cpp │ ├── step_generator.h │ ├── tick_router.h │ ├── trigger_operators.cpp │ ├── trigger_operators.h │ ├── utils.h │ ├── value.cpp │ ├── value.h │ ├── voice_handler.cpp │ ├── voice_handler.h │ ├── wave.cpp │ └── wave.h ├── patches ├── bit_sin.mite ├── bwang.mite ├── default.mite ├── loaded_room.mite ├── test_patch1.mite ├── test_patch2.mite ├── water_wobble.mite ├── whistle.mite ├── whoooo.mite └── womp.mite ├── po ├── .gitignore ├── Makevars └── POTFILES.in ├── rtaudio ├── .gitignore ├── Makefile.am ├── RtAudio.cpp ├── RtAudio.h ├── RtError.h ├── configure.ac ├── contrib │ └── python │ │ └── pyrtaudio │ │ ├── PyRtAudioTest.py │ │ ├── readme │ │ ├── rtaudiomodule.cpp │ │ └── setup.py ├── include │ ├── asio.cpp │ ├── asio.h │ ├── asiodrivers.cpp │ ├── asiodrivers.h │ ├── asiodrvr.h │ ├── asiolist.cpp │ ├── asiolist.h │ ├── asiosys.h │ ├── dsound.h │ ├── ginclude.h │ ├── iasiodrv.h │ ├── iasiothiscallresolver.cpp │ ├── iasiothiscallresolver.h │ └── soundcard.h ├── install ├── librtaudio.pc.in ├── readme ├── rtaudio-config.in └── tests │ ├── Makefile.in │ ├── Windows │ ├── audioprobe.dsp │ ├── duplex.dsp │ ├── playraw.dsp │ ├── playsaw.dsp │ ├── record.dsp │ ├── rtaudio.dsw │ ├── testall.dsp │ └── teststops.dsp │ ├── audioprobe.cpp │ ├── duplex.cpp │ ├── playraw.cpp │ ├── playsaw.cpp │ ├── record.cpp │ ├── testall.cpp │ └── teststops.cpp ├── rtmidi ├── .gitignore ├── Makefile.am ├── RtError.h ├── RtMidi.cpp ├── RtMidi.h ├── configure.ac ├── include │ ├── ks.h │ └── ksmedia.h ├── msw │ ├── readme │ ├── rtmidilib.sln │ └── rtmidilib.vcproj ├── readme ├── rtmidi-config.in └── tests │ ├── Makefile.in │ ├── RtMidi.dsw │ ├── cmidiin.cpp │ ├── cmidiin.dsp │ ├── midiout.cpp │ ├── midiout.dsp │ ├── midiprobe.cpp │ ├── midiprobe.dsp │ ├── qmidiin.cpp │ ├── qmidiin.dsp │ ├── sysextest.cpp │ └── sysextest.dsp └── src ├── Makefile.am ├── cursynth.cpp ├── cursynth.h ├── cursynth_common.h ├── cursynth_engine.cpp ├── cursynth_engine.h ├── cursynth_gui.cpp ├── cursynth_gui.h ├── cursynth_strings.cpp ├── cursynth_strings.h └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Compiled Object files 4 | *.slo 5 | *.lo 6 | *.o 7 | debug 8 | 9 | # Compiled Dynamic libraries 10 | *.so 11 | *.dylib 12 | 13 | # Compiled Static libraries 14 | *.lai 15 | *.la 16 | *.a 17 | 18 | # Executables 19 | cursynth 20 | a.out 21 | 22 | # Autotools 23 | Makefile.in 24 | ar-lib 25 | config.guess 26 | config.rpath 27 | config.sub 28 | config.h.in 29 | *.la 30 | *.lo 31 | *~ 32 | .deps/ 33 | .libs/ 34 | Makefile 35 | aclocal.m4 36 | autom4te.cache 37 | autoscan.log 38 | compile 39 | config.h 40 | config.log 41 | config.status 42 | configure 43 | depcomp 44 | install-sh 45 | libtool 46 | ltmain.sh 47 | m4/ 48 | missing 49 | stamp* 50 | stdin.info 51 | *.tar.gz 52 | stdin.info 53 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Little IO 2 | Matt Tytel 3 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2014-03-15 Matt Tytel 2 | 3 | * patches/*: Edited levels of all patches. 4 | * configure.ac: Bumped version to 1.4 5 | * src/cursynth_gui.cpp: Updated website to gnu.org/software/cursynth 6 | 7 | 2014-01-22 gettextize 8 | 9 | * Makefile.am (ACLOCAL_AMFLAGS): New variable. 10 | (EXTRA_DIST): Add config.rpath, m4/ChangeLog. 11 | * configure.ac (AC_CONFIG_FILES): Add po/Makefile.in. 12 | (AM_GNU_GETTEXT_VERSION): Bump to 0.18.3. 13 | 14 | Copyright 2013-2015 Matt Tytel 15 | Copying and distribution of this file, with or without modification, are 16 | promitted provided the copyright notice and this notice are preserved. 17 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = cJSON rtaudio rtmidi mopo src po doc 2 | EXTRA_DIST = config.rpath patches 3 | 4 | patchesdir = $(pkgdatadir)/patches 5 | patches_DATA = $(top_srcdir)/patches/*.mite 6 | 7 | ACLOCAL_AMFLAGS = -I m4 8 | LDFLAGS += -L/usr/local/opt/gettext/lib 9 | CPPFLAGS += -I/usr/local/opt/gettext/include 10 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | No news is good news. 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | cursynth - a GNU program 2 | ------------ 3 | cursynth is a polyphonic, MIDI enabled, subtractive synth that runs in your 4 | terminal with an ascii interface. 5 | 6 | cursynth will connect to all MIDI devices and send output to the default audio 7 | device on your system. 8 | 9 | ### Building 10 | If you just want to build Cursynth, check out [ftp://ftp.gnu.org/gnu/cursynth] 11 | for latest source releases that don't require as much to build. 12 | 13 | If you want to develop Cursynth, this source is the right place. 14 | Run these commands to build the project from source: 15 | 16 | $ autoreconf -i 17 | $ ./configure 18 | $ make 19 | 20 | And then if you want to install, next run: 21 | 22 | $ sudo make install 23 | 24 | ### Usage 25 | cursynth [--buffer-size OR -b preferred-buffer-size] 26 | [--sample-rate OR -s preferred-sample-rate] 27 | [--version OR -V] 28 | 29 | ### Controls 30 | * awsedftgyhujkolp;' - a playable keyboard (no key up events) 31 | * \`1234567890 - a slider for the current selected control 32 | * up/down - previous/next control 33 | * left/right - decrement/increment control 34 | * F1 (or [shift] + H) - help/controls 35 | * [shift] + L - browse/load patches 36 | * [shift] + S - save patch 37 | * m - arm midi learn 38 | * c - erase midi learn 39 | 40 | ### Requirements: 41 | * OS: Mac OSX or GNU/Linux 42 | * Terminal: a color enabled terminal with minimum 120x44 ascii characters 43 | * If you want key up events, you have to use a MIDI keyboard 44 | 45 | ### TODO: 46 | * Make a LV2 plugin version of cursynth 47 | * More modulation sources and destinations 48 | * Routable Envelopes 49 | * On startup select audio output device 50 | * On startup select MIDI input device 51 | * Lot's more... 52 | 53 | Questions? Feature requests? Bugs? email matthewtytel@gmail.com 54 | 55 | Copyright 2013-2015 Matt Tytel 56 | -------------------------------------------------------------------------------- /cJSON/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Dave Gamble 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /cJSON/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LIBRARIES = libcJSON.a 2 | libcJSON_a_SOURCES = cJSON.c cJSON.h 3 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | # Documentation 2 | mdate-sh 3 | cursynth.info 4 | texinfo.tex 5 | version.texi 6 | stdin.info 7 | *.html 8 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | info_TEXINFOS = cursynth.texi 2 | cursynth_TEXINFOS = cursynth.texi 3 | -------------------------------------------------------------------------------- /mopo/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | 15 | # Executables 16 | mopo_test 17 | a.out 18 | 19 | # Autotools 20 | ar-lib 21 | *.in 22 | *.la 23 | *.lo 24 | *~ 25 | .deps/ 26 | .libs/ 27 | Makefile 28 | aclocal.m4 29 | autom4te.cache 30 | autoscan.log 31 | compile 32 | config.guess 33 | config.h 34 | config.log 35 | config.status 36 | config.sub 37 | configure 38 | depcomp 39 | install-sh 40 | libtool 41 | ltmain.sh 42 | m4/ 43 | missing 44 | stamp* 45 | *.tar.gz 46 | -------------------------------------------------------------------------------- /mopo/AUTHORS: -------------------------------------------------------------------------------- 1 | Little IO 2 | Matt Tytel 3 | -------------------------------------------------------------------------------- /mopo/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtytel/cursynth/578b43cd5d2f310b41b215b7763c7ebfce95b533/mopo/ChangeLog -------------------------------------------------------------------------------- /mopo/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | -------------------------------------------------------------------------------- /mopo/NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtytel/cursynth/578b43cd5d2f310b41b215b7763c7ebfce95b533/mopo/NEWS -------------------------------------------------------------------------------- /mopo/README: -------------------------------------------------------------------------------- 1 | mopo: MOdular and POlyphonic synthesis library. 2 | ----------------------------- 3 | 4 | mopo is an audio synthesis library aimed at creating modular polyphonic synthesizers. 5 | -------------------------------------------------------------------------------- /mopo/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.68]) 5 | AC_INIT([mopo], [0.1], [littleioaudio@gmail.com]) 6 | AM_INIT_AUTOMAKE([-Wall -Werror foreign]) 7 | AM_SILENT_RULES(yes) 8 | AC_CONFIG_SRCDIR([src/delay.cpp]) 9 | 10 | # Checks for programs. 11 | AC_PROG_CXX 12 | AC_PROG_CC 13 | AC_PROG_RANLIB 14 | AM_PROG_AR 15 | 16 | # Checks for libraries. 17 | AC_CHECK_LIB([pthread], [pthread_create]) 18 | 19 | # Checks for header files. 20 | AC_CHECK_HEADERS([limits.h stddef.h stdlib.h string.h strings.h unistd.h]) 21 | 22 | # Checks for typedefs, structures, and compiler characteristics. 23 | AC_C_INLINE 24 | AC_C_RESTRICT 25 | AC_TYPE_SIZE_T 26 | AC_CHECK_TYPES([ptrdiff_t]) 27 | 28 | # Checks for library functions. 29 | AC_FUNC_FORK 30 | AC_FUNC_MALLOC 31 | AC_CHECK_FUNCS([dup2 memset modf pow rmdir strcasecmp strchr strdup strerror]) 32 | 33 | AC_CONFIG_FILES([Makefile 34 | src/Makefile]) 35 | AC_OUTPUT 36 | -------------------------------------------------------------------------------- /mopo/src/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LIBRARIES = libmopo.a 2 | libmopo_a_SOURCES = delay.cpp \ 3 | delay.h \ 4 | envelope.cpp \ 5 | envelope.h \ 6 | feedback.cpp \ 7 | feedback.h \ 8 | filter.cpp \ 9 | filter.h \ 10 | linear_slope.cpp \ 11 | linear_slope.h \ 12 | memory.h \ 13 | midi_lookup.cpp \ 14 | midi_lookup.h \ 15 | mono_panner.cpp \ 16 | mono_panner.h \ 17 | mopo.h \ 18 | operators.cpp \ 19 | operators.h \ 20 | oscillator.cpp \ 21 | oscillator.h \ 22 | processor.cpp \ 23 | processor.h \ 24 | processor_router.cpp \ 25 | processor_router.h \ 26 | send_receive.cpp \ 27 | send_receive.h \ 28 | smooth_filter.cpp \ 29 | smooth_filter.h \ 30 | smooth_value.cpp \ 31 | smooth_value.h \ 32 | step_generator.cpp \ 33 | step_generator.h \ 34 | tick_router.h \ 35 | trigger_operators.cpp \ 36 | trigger_operators.h \ 37 | value.cpp \ 38 | value.h \ 39 | utils.h \ 40 | voice_handler.cpp \ 41 | voice_handler.h \ 42 | wave.cpp \ 43 | wave.h 44 | -------------------------------------------------------------------------------- /mopo/src/delay.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "delay.h" 18 | 19 | namespace mopo { 20 | 21 | Delay::Delay() : Processor(Delay::kNumInputs, 1) { } 22 | 23 | void Delay::process() { 24 | for (int i = 0; i < buffer_size_; ++i) 25 | outputs_[0]->buffer[i] = tick(i); 26 | } 27 | } // namespace mopo 28 | -------------------------------------------------------------------------------- /mopo/src/delay.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef DELAY_H 19 | #define DELAY_H 20 | 21 | #include "memory.h" 22 | #include "processor.h" 23 | 24 | namespace mopo { 25 | 26 | // A signal delay processor with wet/dry, delay time and feedback controls. 27 | // Handles fractional delay amounts through interpolation. 28 | class Delay : public Processor { 29 | public: 30 | enum Inputs { 31 | kAudio, 32 | kWet, 33 | kDelayTime, 34 | kFeedback, 35 | kNumInputs 36 | }; 37 | 38 | Delay(); 39 | 40 | virtual Processor* clone() const { return new Delay(*this); } 41 | virtual void process(); 42 | 43 | protected: 44 | mopo_float tick(int i) { 45 | mopo_float input = inputs_[kAudio]->at(i); 46 | mopo_float wet = inputs_[kWet]->at(i); 47 | mopo_float period = inputs_[kDelayTime]->at(i) * sample_rate_; 48 | mopo_float feedback = inputs_[kFeedback]->at(i); 49 | 50 | mopo_float read = memory_.get(period); 51 | memory_.push(input + read * feedback); 52 | return INTERPOLATE(input, read, wet); 53 | } 54 | 55 | Memory memory_; 56 | }; 57 | } // namespace mopo 58 | 59 | #endif // DELAY_H 60 | -------------------------------------------------------------------------------- /mopo/src/envelope.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "envelope.h" 18 | 19 | #include 20 | 21 | #define KILL_TIME 0.02 22 | 23 | namespace mopo { 24 | 25 | Envelope::Envelope() : 26 | Processor(kNumInputs, kNumOutputs), state_(kReleasing), 27 | current_value_(0), decay_decay_(0), release_decay_(0) { } 28 | 29 | void Envelope::trigger(mopo_float event, int offset) { 30 | if (event == kVoiceOn) 31 | state_ = kKilling; 32 | else if (event == kVoiceOff) { 33 | state_ = kReleasing; 34 | outputs_[kFinished]->trigger(kVoiceOff, offset); 35 | } 36 | else if (event == kVoiceReset) { 37 | state_ = kAttacking; 38 | current_value_ = 0.0; 39 | } 40 | } 41 | 42 | void Envelope::process() { 43 | outputs_[kFinished]->clearTrigger(); 44 | // Only update decay and release rate once per buffer. 45 | mopo_float decay_samples = 46 | sample_rate_ * inputs_[kDecay]->at(buffer_size_ - 1); 47 | decay_decay_ = pow(CLOSE_ENOUGH, 1.0 / decay_samples); 48 | 49 | mopo_float release_samples = 50 | sample_rate_ * inputs_[kRelease]->at(buffer_size_ - 1); 51 | release_decay_ = pow(CLOSE_ENOUGH, 1.0 / release_samples); 52 | 53 | int i = 0; 54 | if (inputs_[kTrigger]->source->triggered) { 55 | int trigger_offset = inputs_[kRelease]->source->trigger_offset; 56 | 57 | for (; i < trigger_offset; ++i) 58 | outputs_[kValue]->buffer[i] = tick(i); 59 | 60 | trigger(inputs_[kTrigger]->source->trigger_value, trigger_offset); 61 | } 62 | 63 | for (; i < buffer_size_; ++i) 64 | outputs_[kValue]->buffer[i] = tick(i); 65 | } 66 | 67 | inline mopo_float Envelope::tick(int i) { 68 | if (state_ == kAttacking) { 69 | if (inputs_[kAttack]->at(i) <= 0) 70 | current_value_ = 1; 71 | else { 72 | mopo_float change = 1.0 / (sample_rate_ * inputs_[kAttack]->at(i)); 73 | current_value_ = CLAMP(current_value_ + change, 0, 1); 74 | } 75 | if (current_value_ >= 1) 76 | state_ = kDecaying; 77 | } 78 | else if (state_ == kDecaying) { 79 | current_value_ = INTERPOLATE(inputs_[kSustain]->at(i), current_value_, 80 | decay_decay_); 81 | } 82 | else if (state_ == kKilling) { 83 | current_value_ -= CLAMP(1 / (KILL_TIME * sample_rate_), 0, 1); 84 | if (current_value_ <= 0) { 85 | outputs_[kFinished]->trigger(kVoiceReset, i); 86 | state_ = kAttacking; 87 | } 88 | } 89 | else if (state_ == kReleasing) 90 | current_value_ *= release_decay_; 91 | return current_value_; 92 | } 93 | } // namespace mopo 94 | -------------------------------------------------------------------------------- /mopo/src/envelope.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef ENVELOPE_H 19 | #define ENVELOPE_H 20 | 21 | #include "processor.h" 22 | 23 | #define CLOSE_ENOUGH (1.0 / 256.0) 24 | 25 | namespace mopo { 26 | 27 | // An ADSR (Attack, Decay, Sustain, Release) Envelope. 28 | // The attack is a linear scale and completes in the exact amount of time. 29 | // The decay and release are exponential and get down to the _CLOSE_ENOUGH_ 30 | // level in the specified amount of time. 31 | // 32 | // The reason for this is that technically the decay and release 33 | // take an extremely long time to finish because they are exponential. But 34 | // users are used to specifying the amount of time the decay or release take 35 | // so we make this compromise of _CLOSE_ENOUGH_. 36 | class Envelope : public Processor { 37 | public: 38 | enum Inputs { 39 | kAttack, 40 | kDecay, 41 | kSustain, 42 | kRelease, 43 | kTrigger, 44 | kNumInputs 45 | }; 46 | 47 | enum Outputs { 48 | kValue, 49 | kFinished, 50 | kNumOutputs 51 | }; 52 | 53 | enum State { 54 | kAttacking, 55 | kDecaying, 56 | kReleasing, 57 | kKilling, 58 | }; 59 | 60 | Envelope(); 61 | 62 | virtual Processor* clone() const { return new Envelope(*this); } 63 | void process(); 64 | void trigger(mopo_float event, int offset); 65 | 66 | private: 67 | mopo_float tick(int i); 68 | 69 | State state_; 70 | mopo_float current_value_; 71 | mopo_float decay_decay_; 72 | mopo_float release_decay_; 73 | }; 74 | } // namespace mopo 75 | 76 | #endif // ENVELOPE_H 77 | -------------------------------------------------------------------------------- /mopo/src/feedback.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "feedback.h" 18 | 19 | #include "processor_router.h" 20 | 21 | namespace mopo { 22 | 23 | void Feedback::process() { 24 | memcpy(buffer_, inputs_[0]->source->buffer, 25 | buffer_size_ * sizeof(mopo_float)); 26 | refreshOutput(); 27 | } 28 | 29 | void Feedback::refreshOutput() { 30 | memcpy(outputs_[0]->buffer, buffer_, MAX_BUFFER_SIZE * sizeof(mopo_float)); 31 | } 32 | } // namespace mopo 33 | -------------------------------------------------------------------------------- /mopo/src/feedback.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef FEEDBACK_H 19 | #define FEEDBACK_H 20 | 21 | #include "processor.h" 22 | 23 | namespace mopo { 24 | 25 | // A special processor for the purpose of feedback loops in the signal flow. 26 | // Feedback can be used for batch buffer feedback processing or sample by 27 | // sample feedback processing. 28 | class Feedback : public Processor { 29 | public: 30 | Feedback() : Processor(1, 1) { } 31 | 32 | virtual Processor* clone() const { return new Feedback(*this); } 33 | virtual void process(); 34 | virtual void refreshOutput(); 35 | 36 | inline void tick(int i) { 37 | buffer_[i] = inputs_[0]->source->buffer[i]; 38 | } 39 | 40 | inline void tickBeginRefreshOutput() { 41 | outputs_[0]->buffer[0] = buffer_[buffer_size_ - 1]; 42 | } 43 | 44 | inline void tickRefreshOutput(int i) { 45 | MOPO_ASSERT(i > 0 && i < buffer_size_); 46 | outputs_[0]->buffer[i] = buffer_[i - 1]; 47 | } 48 | 49 | protected: 50 | mopo_float buffer_[MAX_BUFFER_SIZE]; 51 | }; 52 | } // namespace mopo 53 | 54 | #endif // FEEDBACK_H 55 | -------------------------------------------------------------------------------- /mopo/src/filter.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "filter.h" 18 | 19 | #include 20 | 21 | namespace mopo { 22 | 23 | Filter::Filter() : Processor(Filter::kNumInputs, 1) { 24 | current_type_ = kNumTypes; 25 | current_cutoff_ = 0.0; 26 | current_resonance_ = 0.0; 27 | 28 | in_0_ = in_1_ = in_2_ = 0.0; 29 | out_0_ = out_1_ = 0.0; 30 | past_in_1_ = past_in_2_ = past_out_1_ = past_out_2_ = 0.0; 31 | } 32 | 33 | void Filter::process() { 34 | current_type_ = static_cast(inputs_[kType]->at(0)); 35 | computeCoefficients(current_type_, inputs_[kCutoff]->at(0), 36 | inputs_[kResonance]->at(0)); 37 | 38 | int i = 0; 39 | if (inputs_[kReset]->source->triggered && 40 | inputs_[kReset]->source->trigger_value == kVoiceReset) { 41 | int trigger_offset = inputs_[kReset]->source->trigger_offset; 42 | for (; i < trigger_offset; ++i) 43 | outputs_[0]->buffer[i] = tick(i); 44 | 45 | reset(); 46 | } 47 | for (; i < buffer_size_; ++i) 48 | outputs_[0]->buffer[i] = tick(i); 49 | } 50 | 51 | inline mopo_float Filter::tick(int i) { 52 | mopo_float input = inputs_[kAudio]->at(i); 53 | mopo_float cutoff = inputs_[kCutoff]->at(i); 54 | mopo_float resonance = inputs_[kResonance]->at(i); 55 | 56 | if (cutoff != current_cutoff_ || resonance != current_resonance_) 57 | computeCoefficients(current_type_, cutoff, resonance); 58 | 59 | mopo_float out = input * in_0_ + past_in_1_ * in_1_ + past_in_2_ * in_2_ - 60 | past_out_1_ * out_0_ - past_out_2_ * out_1_; 61 | past_in_2_ = past_in_1_; 62 | past_in_1_ = input; 63 | past_out_2_ = past_out_1_; 64 | past_out_1_ = out; 65 | return out; 66 | } 67 | 68 | inline void Filter::reset() { 69 | past_in_1_ = past_in_2_ = past_out_1_ = past_out_2_ = 0; 70 | } 71 | 72 | inline void Filter::computeCoefficients(Type type, 73 | mopo_float cutoff, 74 | mopo_float resonance) { 75 | mopo_float sf = 1.0 / tan(PI * cutoff / sample_rate_); 76 | mopo_float sf_squared = sf * sf; 77 | mopo_float norm = 1.0 + 1.0 / resonance * sf + sf_squared; 78 | 79 | switch(type) { 80 | case kLP12: { 81 | in_2_ = in_0_ = 1.0 / norm; 82 | in_1_ = 2.0 / norm; 83 | out_0_ = 2.0 * (1.0 - sf_squared) / norm; 84 | out_1_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm; 85 | break; 86 | } 87 | case kHP12: { 88 | in_2_ = in_0_ = sf_squared / norm; 89 | in_1_ = -2.0 * sf_squared / norm; 90 | out_0_ = 2.0 * (1.0 - sf_squared) / norm; 91 | out_1_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm; 92 | break; 93 | } 94 | case kBP12: { 95 | in_2_ = in_0_ = sf / norm; 96 | in_1_ = 0.0; 97 | out_0_ = 2.0 * (1.0 - sf_squared) / norm; 98 | out_1_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm; 99 | break; 100 | } 101 | case kAP12: { 102 | in_0_ = 1.0 / norm; 103 | in_1_ = -2.0 * (1.0 - sf_squared) / norm; 104 | in_2_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm; 105 | out_0_ = -in_1_; 106 | out_1_ = in_2_; 107 | break; 108 | } 109 | default: 110 | in_2_ = in_1_ = in_0_ = out_1_ = out_0_ = 0.0; 111 | } 112 | 113 | current_cutoff_ = cutoff; 114 | current_resonance_ = resonance; 115 | } 116 | } // namespace mopo 117 | -------------------------------------------------------------------------------- /mopo/src/filter.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef FILTER_H 19 | #define FILTER_H 20 | 21 | #include "processor.h" 22 | 23 | namespace mopo { 24 | 25 | // 12 dB per octave filters. There is a low pass filter, high pass filter, 26 | // band pass filter, and all pass filter. 27 | class Filter : public Processor { 28 | public: 29 | enum Inputs { 30 | kAudio, 31 | kType, 32 | kCutoff, 33 | kResonance, 34 | kReset, 35 | kNumInputs 36 | }; 37 | 38 | enum Type { 39 | kLP12, 40 | kHP12, 41 | kBP12, 42 | kAP12, 43 | kNumTypes, 44 | }; 45 | 46 | Filter(); 47 | 48 | virtual Processor* clone() const { return new Filter(*this); } 49 | virtual void process(); 50 | 51 | private: 52 | mopo_float tick(int i); 53 | void reset(); 54 | void computeCoefficients(Type type, mopo_float cutoff, 55 | mopo_float resonance); 56 | 57 | Type current_type_; 58 | mopo_float current_cutoff_, current_resonance_; 59 | 60 | mopo_float in_0_, in_1_, in_2_; 61 | mopo_float out_0_, out_1_; 62 | 63 | mopo_float past_in_1_, past_in_2_; 64 | mopo_float past_out_1_, past_out_2_; 65 | }; 66 | } // namespace mopo 67 | 68 | #endif // FILTER_H 69 | -------------------------------------------------------------------------------- /mopo/src/linear_slope.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "linear_slope.h" 18 | 19 | #include "utils.h" 20 | 21 | #include 22 | 23 | namespace mopo { 24 | 25 | LinearSlope::LinearSlope() : Processor(kNumInputs, 1) { 26 | last_value_ = 0.0; 27 | } 28 | 29 | void LinearSlope::process() { 30 | int i = 0; 31 | if (inputs_[kTriggerJump]->source->triggered) { 32 | int trigger_offset = inputs_[kTriggerJump]->source->trigger_offset; 33 | for (; i < trigger_offset; ++i) { 34 | last_value_ = tick(i); 35 | outputs_[0]->buffer[i] = last_value_; 36 | } 37 | 38 | last_value_ = inputs_[kTarget]->at(i); 39 | } 40 | 41 | for (; i < buffer_size_; ++i) { 42 | last_value_ = tick(i); 43 | outputs_[0]->buffer[i] = last_value_; 44 | } 45 | } 46 | 47 | inline mopo_float LinearSlope::tick(int i) { 48 | mopo_float target = inputs_[kTarget]->at(i); 49 | if (utils::closeToZero(inputs_[kRunSeconds]->at(i))) 50 | return inputs_[kTarget]->at(i); 51 | 52 | mopo_float increment = 1.0 / (sample_rate_ * inputs_[kRunSeconds]->at(0)); 53 | if (target <= last_value_) 54 | return CLAMP(last_value_ - increment, target, last_value_); 55 | return CLAMP(last_value_ + increment, last_value_, target); 56 | } 57 | } // namespace mopo 58 | -------------------------------------------------------------------------------- /mopo/src/linear_slope.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef LINEAR_SLOPE_H 19 | #define LINEAR_SLOPE_H 20 | 21 | #include "value.h" 22 | 23 | namespace mopo { 24 | 25 | // A processor that will slope to the target value over a given amount of 26 | // time. Useful for portamento or smoothing out values. 27 | class LinearSlope : public Processor { 28 | public: 29 | enum Inputs { 30 | kTarget, 31 | kRunSeconds, 32 | kTriggerJump, 33 | kNumInputs 34 | }; 35 | 36 | LinearSlope(); 37 | 38 | virtual Processor* clone() const { return new LinearSlope(*this); } 39 | virtual void process(); 40 | 41 | private: 42 | mopo_float tick(int i); 43 | 44 | mopo_float last_value_; 45 | }; 46 | } // namespace mopo 47 | 48 | #endif // LINEAR_SLOPE_H 49 | -------------------------------------------------------------------------------- /mopo/src/memory.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef MEMORY_H 19 | #define MEMORY_H 20 | 21 | #include "mopo.h" 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // MAX_MEMORY must be a power of 2. 28 | #define MAX_MEMORY 1048576 29 | #define MEMORY_BITMASK 1048575 30 | 31 | namespace mopo { 32 | 33 | // A processor utility to store a stream of data for later lookup. 34 | class Memory { 35 | public: 36 | Memory() : offset_(0) { 37 | memset(memory_, 0, MAX_MEMORY * sizeof(mopo_float)); 38 | } 39 | 40 | inline void push(mopo_float sample) { 41 | offset_ = (offset_ + 1) & MEMORY_BITMASK; 42 | memory_[offset_] = sample; 43 | } 44 | 45 | inline mopo_float getIndex(int index) const { 46 | return memory_[(offset_ - index) & MEMORY_BITMASK]; 47 | } 48 | 49 | inline mopo_float get(mopo_float past) const { 50 | double float_index; 51 | mopo_float sample_fraction = modf(past, &float_index); 52 | int index = std::max(float_index, 1); 53 | 54 | // TODO(mtytel): Quadratic or all-pass interpolation is better. 55 | mopo_float from = getIndex(index - 1); 56 | mopo_float to = getIndex(index); 57 | return INTERPOLATE(from, to, sample_fraction); 58 | } 59 | 60 | protected: 61 | mopo_float memory_[MAX_MEMORY]; 62 | unsigned int offset_; 63 | }; 64 | } // namespace mopo 65 | 66 | #endif // MEMORY_H 67 | -------------------------------------------------------------------------------- /mopo/src/midi_lookup.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "midi_lookup.h" 18 | 19 | namespace mopo { 20 | 21 | const MidiLookupSingleton MidiLookup::lookup_; 22 | } // namespace mopo 23 | -------------------------------------------------------------------------------- /mopo/src/midi_lookup.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef MIDI_LOOKUP_H 19 | #define MIDI_LOOKUP_H 20 | 21 | #include "mopo.h" 22 | 23 | #include 24 | 25 | #define MIDI_0_FREQUENCY 8.1757989156 26 | #define NOTES_PER_OCTAVE 12 27 | #define CENTS_PER_NOTE 100 28 | #define MAX_CENTS (MIDI_SIZE * CENTS_PER_NOTE) 29 | 30 | namespace mopo { 31 | 32 | class MidiLookupSingleton { 33 | public: 34 | MidiLookupSingleton() { 35 | mopo_float cents_per_octave = CENTS_PER_NOTE * NOTES_PER_OCTAVE; 36 | for (int i = 0; i <= MAX_CENTS; ++i) { 37 | frequency_lookup_[i] = MIDI_0_FREQUENCY * 38 | pow(2, i / cents_per_octave); 39 | } 40 | } 41 | 42 | mopo_float centsLookup(mopo_float cents_from_0) const { 43 | if (cents_from_0 >= MAX_CENTS) 44 | return frequency_lookup_[MAX_CENTS]; 45 | if (cents_from_0 <= 0) 46 | return frequency_lookup_[0]; 47 | 48 | int full_cents = cents_from_0; 49 | mopo_float fraction_cents = cents_from_0 - full_cents; 50 | 51 | return INTERPOLATE(frequency_lookup_[full_cents], 52 | frequency_lookup_[full_cents + 1], fraction_cents); 53 | } 54 | 55 | private: 56 | mopo_float frequency_lookup_[MAX_CENTS + 1]; 57 | }; 58 | 59 | class MidiLookup { 60 | public: 61 | static mopo_float centsLookup(mopo_float cents_from_0) { 62 | return lookup_.centsLookup(cents_from_0); 63 | } 64 | 65 | private: 66 | static const MidiLookupSingleton lookup_; 67 | }; 68 | } // namespace mopo 69 | 70 | #endif // MIDI_LOOKUP_H 71 | -------------------------------------------------------------------------------- /mopo/src/mono_panner.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "mono_panner.h" 18 | 19 | #include "mopo.h" 20 | #include "wave.h" 21 | 22 | #include 23 | 24 | #define LEFT_ROTATION 100.325 25 | #define RIGHT_ROTATION 100.125 26 | 27 | namespace mopo { 28 | 29 | MonoPanner::MonoPanner() : 30 | Processor(MonoPanner::kNumInputs, MonoPanner::kNumOutputs) { } 31 | 32 | void MonoPanner::process() { 33 | double integral; 34 | for (int i = 0; i < buffer_size_; ++i) { 35 | mopo_float audio = inputs_[kAudio]->at(i); 36 | mopo_float pan = inputs_[kPan]->at(i); 37 | mopo_float left_gain = Wave::fullsin(modf(pan + LEFT_ROTATION, 38 | &integral)); 39 | mopo_float right_gain = Wave::fullsin(modf(pan + RIGHT_ROTATION, 40 | &integral)); 41 | 42 | outputs_[kLeft]->buffer[i] = audio * left_gain; 43 | outputs_[kRight]->buffer[i] = audio * right_gain; 44 | } 45 | } 46 | } // namespace mopo 47 | -------------------------------------------------------------------------------- /mopo/src/mono_panner.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef MONO_PANNER_H 19 | #define MONO_PANNER_H 20 | 21 | #include "processor.h" 22 | 23 | namespace mopo { 24 | 25 | // A processor that will split a single signal into two signals, left and 26 | // right. The amplitude of the two outputs is set by the pan amount, ranging 27 | // from all the way left, all the way right, or equally split. 28 | class MonoPanner : public Processor { 29 | public: 30 | enum Inputs { 31 | kAudio, 32 | kPan, 33 | kNumInputs 34 | }; 35 | 36 | enum Outputs { 37 | kLeft, 38 | kRight, 39 | kNumOutputs 40 | }; 41 | 42 | MonoPanner(); 43 | 44 | virtual Processor* clone() const { return new MonoPanner(*this); } 45 | virtual void process(); 46 | }; 47 | } // namespace mopo 48 | 49 | #endif // MONO_PANNER_H 50 | -------------------------------------------------------------------------------- /mopo/src/mopo.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef MOPO_H 19 | #define MOPO_H 20 | 21 | // Utilities. 22 | #define UNUSED(x) (void)(x) 23 | #define CLAMP(v, s, b) ((v) < (s) ? (s) : ((v) > (b) ? (b) : (v))) 24 | #define INTERPOLATE(s, e, f) ((s) + (f) * ((e) - (s))) 25 | 26 | // Debugging. 27 | #define DEBUG 28 | #ifdef DEBUG 29 | #include 30 | #define MOPO_ASSERT(x) assert(x) 31 | #else 32 | #define MOPO_ASSERT(x) (void)(x) 33 | #endif // DEBUG 34 | 35 | namespace mopo { 36 | 37 | const double PI = 3.1415926535897932384626433832795; 38 | const int MAX_BUFFER_SIZE = 4096; 39 | const int DEFAULT_BUFFER_SIZE = 64; 40 | const int DEFAULT_SAMPLE_RATE = 44100; 41 | const int MIDI_SIZE = 128; 42 | const int PPQ = 15360; // Pulses per quarter note. 43 | 44 | typedef double mopo_float; 45 | 46 | // Common types of events across different Processors. 47 | enum VoiceEvent { 48 | kVoiceOff, // Stop. (e.g. release in an envelope) 49 | kVoiceOn, // Start. (e.g. start attack in an envelope) 50 | kVoiceReset, // Reset. Immediately reset to initial state. 51 | }; 52 | } // namespace mopo 53 | 54 | #endif // MOPO_H 55 | -------------------------------------------------------------------------------- /mopo/src/operators.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "operators.h" 18 | 19 | namespace mopo { 20 | 21 | void Operator::process() { 22 | for (int i = 0; i < buffer_size_; ++i) 23 | tick(i); 24 | } 25 | 26 | void VariableAdd::process() { 27 | memset(outputs_[0]->buffer, 0, buffer_size_ * sizeof(mopo_float)); 28 | 29 | int num_inputs = inputs_.size(); 30 | for (int i = 0; i < num_inputs; ++i) { 31 | if (inputs_[i]->source != &Processor::null_source_) { 32 | for (int s = 0; s < buffer_size_; ++s) 33 | outputs_[0]->buffer[s] += inputs_[i]->at(s); 34 | } 35 | } 36 | } 37 | } // namespace mopo 38 | -------------------------------------------------------------------------------- /mopo/src/oscillator.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "oscillator.h" 18 | 19 | #include 20 | 21 | namespace mopo { 22 | 23 | Oscillator::Oscillator() : Processor(kNumInputs, 1), 24 | offset_(0.0), waveform_(Wave::kSin) { } 25 | 26 | void Oscillator::preprocess() { 27 | waveform_ = static_cast(inputs_[kWaveform]->at(0)); 28 | } 29 | 30 | void Oscillator::process() { 31 | preprocess(); 32 | 33 | int i = 0; 34 | if (inputs_[kReset]->source->triggered && 35 | inputs_[kReset]->source->trigger_value == kVoiceReset) { 36 | int trigger_offset = inputs_[kReset]->source->trigger_offset; 37 | for (; i < trigger_offset; ++i) 38 | tick(i); 39 | 40 | offset_ = 0.0; 41 | } 42 | for (; i < buffer_size_; ++i) 43 | tick(i); 44 | } 45 | } // namespace mopo 46 | -------------------------------------------------------------------------------- /mopo/src/oscillator.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef OSCILLATOR_H 19 | #define OSCILLATOR_H 20 | 21 | #include "processor.h" 22 | #include "wave.h" 23 | 24 | namespace mopo { 25 | 26 | // A processor that produces an oscillation stream based on the input 27 | // frequency, phase, and waveform. You can reset the waveform stream using 28 | // the reset input. 29 | class Oscillator : public Processor { 30 | public: 31 | enum Inputs { 32 | kFrequency, 33 | kPhase, 34 | kWaveform, 35 | kReset, 36 | kNumInputs 37 | }; 38 | 39 | Oscillator(); 40 | 41 | virtual Processor* clone() const { return new Oscillator(*this); } 42 | void preprocess(); 43 | void process(); 44 | 45 | inline void tick(int i) { 46 | mopo_float frequency = inputs_[kFrequency]->at(i); 47 | mopo_float phase = inputs_[kPhase]->at(i); 48 | 49 | offset_ += frequency / sample_rate_; 50 | double integral; 51 | offset_ = modf(offset_, &integral); 52 | outputs_[0]->buffer[i] = 53 | Wave::blwave(waveform_, offset_ + phase, frequency); 54 | } 55 | 56 | protected: 57 | mopo_float offset_; 58 | Wave::Type waveform_; 59 | }; 60 | } // namespace mopo 61 | 62 | #endif // OSCILLATOR_H 63 | -------------------------------------------------------------------------------- /mopo/src/processor.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "processor.h" 18 | 19 | #include "processor_router.h" 20 | 21 | namespace mopo { 22 | 23 | const Processor::Output Processor::null_source_; 24 | 25 | Processor::Processor(int num_inputs, int num_outputs) : 26 | sample_rate_(DEFAULT_SAMPLE_RATE), buffer_size_(DEFAULT_BUFFER_SIZE), 27 | router_(0) { 28 | for (int i = 0; i < num_inputs; ++i) { 29 | Input* input = new Input(); 30 | 31 | // All inputs start off with null input. 32 | input->source = &Processor::null_source_; 33 | registerInput(input); 34 | } 35 | 36 | for (int i = 0; i < num_outputs; ++i) { 37 | Output* output = new Output(); 38 | 39 | // All outputs are owned by this Processor. 40 | output->owner = this; 41 | registerOutput(output); 42 | } 43 | } 44 | 45 | void Processor::plug(const Output* source) { 46 | plug(source, 0); 47 | } 48 | 49 | void Processor::plug(const Output* source, unsigned int input_index) { 50 | MOPO_ASSERT(input_index < inputs_.size()); 51 | MOPO_ASSERT(source); 52 | 53 | inputs_[input_index]->source = source; 54 | 55 | if (router_) 56 | router_->connect(this, source, input_index); 57 | } 58 | 59 | void Processor::plug(const Processor* source) { 60 | plug(source, 0); 61 | } 62 | 63 | void Processor::plug(const Processor* source, unsigned int input_index) { 64 | plug(source->output(), input_index); 65 | } 66 | 67 | void Processor::plugNext(const Output* source) { 68 | for (size_t i = 0; i < inputs_.size(); ++i) { 69 | if (inputs_[i]->source == &Processor::null_source_) { 70 | plug(source, i); 71 | return; 72 | } 73 | } 74 | } 75 | 76 | void Processor::plugNext(const Processor* source) { 77 | plugNext(source->output()); 78 | } 79 | 80 | void Processor::unplugIndex(unsigned int input_index) { 81 | inputs_[input_index]->source = &Processor::null_source_; 82 | } 83 | 84 | void Processor::unplug(const Output* source) { 85 | for (unsigned int i = 0; i < inputs_.size(); ++i) { 86 | if (inputs_[i]->source == source) 87 | inputs_[i]->source = &Processor::null_source_; 88 | } 89 | } 90 | 91 | void Processor::unplug(const Processor* source) { 92 | for (unsigned int i = 0; i < inputs_.size(); ++i) { 93 | if (inputs_[i]->source->owner == source) 94 | inputs_[i]->source = &Processor::null_source_; 95 | } 96 | } 97 | 98 | void Processor::registerInput(Input* input) { 99 | inputs_.push_back(input); 100 | if (router_ && input->source != &Processor::null_source_) 101 | router_->connect(this, input->source, inputs_.size() - 1); 102 | } 103 | 104 | void Processor::registerOutput(Output* output) { 105 | outputs_.push_back(output); 106 | } 107 | 108 | Processor::Input* Processor::input(unsigned int index) const { 109 | MOPO_ASSERT(index < inputs_.size()); 110 | 111 | return inputs_[index]; 112 | } 113 | 114 | Processor::Output* Processor::output(unsigned int index) const { 115 | MOPO_ASSERT(index < outputs_.size()); 116 | 117 | return outputs_[index]; 118 | } 119 | } // namespace mopo 120 | -------------------------------------------------------------------------------- /mopo/src/processor.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef PROCESSOR_H 19 | #define PROCESSOR_H 20 | 21 | #include "mopo.h" 22 | 23 | #include 24 | #include 25 | 26 | namespace mopo { 27 | 28 | class ProcessorRouter; 29 | 30 | class Processor { 31 | public: 32 | // An output port from the Processor. 33 | struct Output { 34 | Output() { 35 | owner = 0; 36 | clearBuffer(); 37 | clearTrigger(); 38 | } 39 | 40 | void trigger(mopo_float value, int offset = 0) { 41 | triggered = true; 42 | trigger_offset = offset; 43 | trigger_value = value; 44 | } 45 | 46 | void clearTrigger() { 47 | triggered = false; 48 | trigger_offset = 0; 49 | trigger_value = 0.0; 50 | } 51 | 52 | void clearBuffer() { 53 | memset(buffer, 0, MAX_BUFFER_SIZE * sizeof(mopo_float)); 54 | } 55 | 56 | const Processor* owner; 57 | mopo_float buffer[MAX_BUFFER_SIZE]; 58 | 59 | bool triggered; 60 | int trigger_offset; 61 | mopo_float trigger_value; 62 | }; 63 | 64 | // An input port to the Processor. You can plug an Output into on of 65 | // these inputs. 66 | struct Input { 67 | Input() { source = 0; } 68 | 69 | const Output* source; 70 | 71 | mopo_float at(int i) const { return source->buffer[i]; } 72 | }; 73 | 74 | Processor(int num_inputs, int num_outputs); 75 | 76 | // Currently need to override this boiler plate clone. 77 | // TODO(mtytel): Should probably make a macro for this. 78 | virtual Processor* clone() const = 0; 79 | 80 | // Subclasses override this for main processing code. 81 | virtual void process() = 0; 82 | 83 | // Subclasses should override this if they need to adjust for change in 84 | // sample rate. 85 | virtual void setSampleRate(int sample_rate) { 86 | sample_rate_ = sample_rate; 87 | } 88 | 89 | virtual void setBufferSize(int buffer_size) { 90 | buffer_size_ = buffer_size; 91 | } 92 | 93 | // Attaches an output to an input in this processor. 94 | void plug(const Output* source); 95 | void plug(const Output* source, unsigned int input_index); 96 | void plug(const Processor* source); 97 | void plug(const Processor* source, unsigned int input_index); 98 | 99 | // Attaches an output to the first available input in this processor. 100 | void plugNext(const Output* source); 101 | void plugNext(const Processor* source); 102 | 103 | // Remove a connection between two processors. 104 | virtual void unplugIndex(unsigned int input_index); 105 | virtual void unplug(const Output* source); 106 | virtual void unplug(const Processor* source); 107 | 108 | // Sets the ProcessorRouter that will own this Processor. 109 | void router(ProcessorRouter* router) { router_ = router; } 110 | 111 | // Returns the ProcessorRouter that owns this Processor. 112 | const ProcessorRouter* router() const { return router_; } 113 | 114 | virtual void registerInput(Input* input); 115 | virtual void registerOutput(Output* output); 116 | 117 | virtual int numInputs() const { return inputs_.size(); } 118 | virtual int numOutputs() const { return outputs_.size(); } 119 | 120 | // Returns the Input port corresponding to the passed in index. 121 | Input* input(unsigned int index = 0) const; 122 | 123 | // Returns the Output port corresponding to the passed in index. 124 | Output* output(unsigned int index = 0) const; 125 | 126 | protected: 127 | int sample_rate_; 128 | int buffer_size_; 129 | 130 | std::vector inputs_; 131 | std::vector outputs_; 132 | 133 | ProcessorRouter* router_; 134 | 135 | static const Output null_source_; 136 | }; 137 | } // namespace mopo 138 | 139 | #endif // PROCESSOR_H 140 | -------------------------------------------------------------------------------- /mopo/src/processor_router.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef PROCESSOR_ROUTER_H 19 | #define PROCESSOR_ROUTER_H 20 | 21 | #include "processor.h" 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace mopo { 28 | 29 | class Feedback; 30 | 31 | class ProcessorRouter : public Processor { 32 | public: 33 | ProcessorRouter(int num_inputs = 0, int num_outputs = 0); 34 | ProcessorRouter(const ProcessorRouter& original); 35 | 36 | virtual Processor* clone() const { return new ProcessorRouter(*this); } 37 | virtual void process(); 38 | virtual void setSampleRate(int sample_rate); 39 | virtual void setBufferSize(int buffer_size); 40 | 41 | virtual void addProcessor(Processor* processor); 42 | virtual void removeProcessor(const Processor* processor); 43 | 44 | // Any time new dependencies are added into the ProcessorRouter graph, we 45 | // should call _connect_ on the destination Processor and source Output. 46 | void connect(Processor* destination, const Output* source, int index); 47 | bool isDownstream(const Processor* first, const Processor* second); 48 | bool areOrdered(const Processor* first, const Processor* second); 49 | 50 | protected: 51 | // When we create a cycle into the ProcessorRouter graph, we must insert 52 | // a Feedback node and add it here. 53 | virtual void addFeedback(Feedback* feedback); 54 | 55 | // Makes sure _processor_ runs in a topologically sorted order in 56 | // relation to all other Processors in _this_. 57 | void reorder(Processor* processor); 58 | 59 | // Ensures we have all copies of all processors and feedback processors. 60 | virtual void updateAllProcessors(); 61 | 62 | // Returns the ancestor of _processor_ which is a child of _this_. 63 | // Returns NULL if _processor_ is not a descendant of _this_. 64 | const Processor* getContext(const Processor* processor); 65 | std::set getDependencies(const Processor* processor); 66 | 67 | std::vector* order_; 68 | std::map processors_; 69 | 70 | std::vector* feedback_order_; 71 | std::map feedback_processors_; 72 | }; 73 | } // namespace mopo 74 | 75 | #endif // PROCESSOR_ROUTER_H 76 | -------------------------------------------------------------------------------- /mopo/src/send_receive.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "send_receive.h" 18 | 19 | #include "processor_router.h" 20 | 21 | namespace mopo { 22 | 23 | Send::Send() : Processor(1, 1) { 24 | memory_output_ = new MemoryOutput(); 25 | memory_output_->owner = this; 26 | memory_output_->memory = &memory_; 27 | } 28 | 29 | void Send::process() { 30 | for (int i = 0; i < buffer_size_; ++i) 31 | memory_.push(inputs_[0]->at(i)); 32 | memory_output_->memory = &memory_; 33 | } 34 | 35 | Receive::Receive() : Processor(kNumInputs, 1) { 36 | memory_input_ = new MemoryInput(); 37 | memory_input_->owner = this; 38 | } 39 | 40 | void Receive::process() { 41 | mopo_float adjust = buffer_size_; 42 | if (router_ && !router_->areOrdered(memory_input_->source->owner, 43 | memory_input_->owner)) { 44 | adjust = 0; 45 | } 46 | 47 | for (int i = 0; i < buffer_size_; ++i) { 48 | mopo_float time = inputs_[kDelayTime]->at(i) * sample_rate_ + adjust; 49 | outputs_[0]->buffer[i] = memory_input_->get(time); 50 | adjust -= 1.0; 51 | } 52 | } 53 | 54 | void Receive::setSend(const Send* send, bool dependent) { 55 | memory_input_->source = send->memory_output(); 56 | if (dependent) 57 | plug(send, kDependent); 58 | } 59 | } // namespace mopo 60 | -------------------------------------------------------------------------------- /mopo/src/send_receive.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef SEND_RECEIVE_H 19 | #define SEND_RECEIVE_H 20 | 21 | #include "memory.h" 22 | #include "processor.h" 23 | 24 | // TODO(mtytel): This classes don't work with polyphony. Fix that. 25 | 26 | namespace mopo { 27 | 28 | class Send; 29 | class Receive; 30 | 31 | struct MemoryOutput { 32 | MemoryOutput() : owner(0), memory(0) { } 33 | 34 | const Send* owner; 35 | Memory* memory; 36 | 37 | inline mopo_float get(mopo_float past) const { 38 | return memory->get(past); 39 | } 40 | }; 41 | 42 | struct MemoryInput { 43 | MemoryInput() : owner(0), source(0) { } 44 | 45 | const Receive* owner; 46 | const MemoryOutput* source; 47 | 48 | inline mopo_float get(mopo_float past) const { 49 | return source->get(past); 50 | } 51 | }; 52 | 53 | class Send : public Processor { 54 | public: 55 | Send(); 56 | 57 | virtual Processor* clone() const { return new Send(*this); } 58 | virtual void process(); 59 | 60 | inline mopo_float get(mopo_float past) const { 61 | return memory_.get(past); 62 | } 63 | 64 | const MemoryOutput* memory_output() const { return memory_output_; } 65 | 66 | protected: 67 | Memory memory_; 68 | 69 | MemoryOutput* memory_output_; 70 | }; 71 | 72 | class Receive : public Processor { 73 | public: 74 | enum Inputs { 75 | kDependent, 76 | kDelayTime, 77 | kNumInputs 78 | }; 79 | 80 | Receive(); 81 | 82 | virtual Processor* clone() const { return new Receive(*this); } 83 | virtual void process(); 84 | 85 | void setSend(const Send* send, bool dependent = true); 86 | 87 | protected: 88 | MemoryInput* memory_input_; 89 | }; 90 | } // namespace mopo 91 | 92 | #endif // SEND_RECEIVE_H 93 | -------------------------------------------------------------------------------- /mopo/src/smooth_filter.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "smooth_filter.h" 18 | 19 | namespace mopo { 20 | 21 | SmoothFilter::SmoothFilter() : Processor(SmoothFilter::kNumInputs, 1) { 22 | last_value_ = 0.0; 23 | } 24 | 25 | void SmoothFilter::process() { 26 | mopo_float decay = inputs_[kDecay]->at(0); 27 | 28 | for (int i = 0; i < buffer_size_; ++i) { 29 | mopo_float target = inputs_[kTarget]->at(i); 30 | last_value_ = INTERPOLATE(last_value_, target, decay); 31 | outputs_[0]->buffer[i] = last_value_; 32 | } 33 | } 34 | } // namespace mopo 35 | -------------------------------------------------------------------------------- /mopo/src/smooth_filter.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef SMOOTH_FILTER_H 19 | #define SMOOTH_FILTER_H 20 | 21 | #include "processor.h" 22 | 23 | namespace mopo { 24 | 25 | class SmoothFilter : public Processor { 26 | public: 27 | enum Inputs { 28 | kTarget, 29 | kDecay, 30 | kTriggerJump, 31 | kNumInputs 32 | }; 33 | 34 | SmoothFilter(); 35 | 36 | virtual Processor* clone() const { return new SmoothFilter(*this); } 37 | virtual void process(); 38 | 39 | private: 40 | mopo_float last_value_; 41 | }; 42 | } // namespace mopo 43 | 44 | #endif // FILTER_H 45 | -------------------------------------------------------------------------------- /mopo/src/smooth_value.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "smooth_value.h" 18 | 19 | #include 20 | 21 | #define SMOOTH_CUTOFF 3.0 22 | 23 | namespace mopo { 24 | 25 | SmoothValue::SmoothValue(mopo_float value) : 26 | Value(value), target_value_(value) { } 27 | 28 | void SmoothValue::setSampleRate(int sample_rate) { 29 | sample_rate_ = sample_rate; 30 | decay_ = 1 - exp(-2.0 * PI * SMOOTH_CUTOFF / sample_rate_); 31 | } 32 | 33 | void SmoothValue::process() { 34 | for (int i = 0; i < buffer_size_; ++i) 35 | outputs_[0]->buffer[i] = tick(); 36 | } 37 | 38 | inline mopo_float SmoothValue::tick() { 39 | value_ = INTERPOLATE(value_, target_value_, decay_); 40 | return value_; 41 | } 42 | } // namespace mopo 43 | -------------------------------------------------------------------------------- /mopo/src/smooth_value.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef SMOOTH_VALUE_H 19 | #define SMOOTH_VALUE_H 20 | 21 | #include "value.h" 22 | 23 | namespace mopo { 24 | 25 | class SmoothValue : public Value { 26 | public: 27 | SmoothValue(mopo_float value = 0.0); 28 | 29 | virtual Processor* clone() const { return new SmoothValue(*this); } 30 | virtual void process(); 31 | 32 | virtual void setSampleRate(int sample_rate); 33 | 34 | void set(mopo_float value) { target_value_ = value; } 35 | void setHard(mopo_float value) { 36 | Value::set(value); 37 | target_value_ = value; 38 | } 39 | 40 | private: 41 | mopo_float tick(); 42 | 43 | mopo_float target_value_; 44 | mopo_float decay_; 45 | }; 46 | } // namespace mopo 47 | 48 | #endif // SMOOTH_VALUE_H 49 | -------------------------------------------------------------------------------- /mopo/src/step_generator.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "step_generator.h" 18 | 19 | #include 20 | 21 | namespace mopo { 22 | 23 | StepGenerator::StepGenerator(int max_steps) : 24 | Processor(kNumInputs + max_steps, 1), offset_(0.0), current_step_(0) { } 25 | 26 | void StepGenerator::process() { 27 | unsigned int num_steps = static_cast(inputs_[kNumSteps]->at(0)); 28 | 29 | int i = 0; 30 | if (inputs_[kReset]->source->triggered && 31 | inputs_[kReset]->source->trigger_value == kVoiceReset) 32 | i = inputs_[kReset]->source->trigger_offset; 33 | 34 | mopo_float total = 0.0; 35 | for (; i < buffer_size_; ++i) 36 | total += inputs_[kFrequency]->at(i); 37 | 38 | total /= sample_rate_; 39 | double integral; 40 | offset_ = modf(offset_ + total, &integral); 41 | current_step_ = (current_step_ + num_steps) % num_steps; 42 | 43 | for (i = 0; i < buffer_size_; ++i) 44 | outputs_[0]->buffer[i] = inputs_[kSteps + current_step_]->at(i); 45 | } 46 | } // namespace mopo 47 | -------------------------------------------------------------------------------- /mopo/src/step_generator.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef STEP_GENERATOR_H 19 | #define STEP_GENERATOR_H 20 | 21 | #include "processor.h" 22 | 23 | #define DEFAULT_MAX_STEPS 128 24 | 25 | namespace mopo { 26 | 27 | class StepGenerator : public Processor { 28 | public: 29 | enum Inputs { 30 | kFrequency, 31 | kNumSteps, 32 | kReset, 33 | kSteps, 34 | kNumInputs 35 | }; 36 | 37 | StepGenerator(int max_steps = DEFAULT_MAX_STEPS); 38 | 39 | virtual Processor* clone() const { return new StepGenerator(*this); } 40 | 41 | void process(); 42 | 43 | protected: 44 | mopo_float offset_; 45 | unsigned int current_step_; 46 | }; 47 | } // namespace mopo 48 | 49 | #endif // STEP_GENERATOR_H 50 | -------------------------------------------------------------------------------- /mopo/src/tick_router.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef TICK_ROUTER_H 19 | #define TICK_ROUTER_H 20 | 21 | #include "processor_router.h" 22 | 23 | namespace mopo { 24 | 25 | class TickRouter : public ProcessorRouter { 26 | public: 27 | TickRouter(int num_inputs = 0, int num_outputs = 0) : 28 | ProcessorRouter(num_inputs, num_outputs) { } 29 | 30 | virtual void process() = 0; 31 | virtual void tick(int i) = 0; 32 | }; 33 | } // namespace mopo 34 | 35 | #endif // PROCESSOR_ROUTER_H 36 | -------------------------------------------------------------------------------- /mopo/src/trigger_operators.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "trigger_operators.h" 18 | 19 | namespace mopo { 20 | 21 | TriggerCombiner::TriggerCombiner() : Processor(2, 1) { } 22 | 23 | void TriggerCombiner::process() { 24 | outputs_[0]->clearTrigger(); 25 | 26 | if (inputs_[0]->source->triggered) { 27 | outputs_[0]->trigger(inputs_[0]->source->trigger_value, 28 | inputs_[0]->source->trigger_offset); 29 | } 30 | else if (inputs_[1]->source->triggered) { 31 | outputs_[0]->trigger(inputs_[1]->source->trigger_value, 32 | inputs_[1]->source->trigger_offset); 33 | } 34 | } 35 | 36 | TriggerWait::TriggerWait() : Processor(kNumInputs, 1) { } 37 | 38 | void TriggerWait::waitTrigger(mopo_float trigger_value) { 39 | waiting_ = true; 40 | trigger_value_ = trigger_value; 41 | } 42 | 43 | void TriggerWait::sendTrigger(int trigger_offset) { 44 | if (waiting_) 45 | outputs_[0]->trigger(trigger_value_, trigger_offset); 46 | waiting_ = false; 47 | } 48 | 49 | void TriggerWait::process() { 50 | outputs_[0]->clearTrigger(); 51 | 52 | if (inputs_[kWait]->source->triggered && 53 | inputs_[kTrigger]->source->triggered) { 54 | 55 | if (inputs_[kWait]->source->trigger_offset <= 56 | inputs_[kTrigger]->source->trigger_offset) { 57 | waitTrigger(inputs_[kWait]->source->trigger_value); 58 | sendTrigger(inputs_[kTrigger]->source->trigger_offset); 59 | } 60 | else { 61 | sendTrigger(inputs_[kTrigger]->source->trigger_offset); 62 | waitTrigger(inputs_[kWait]->source->trigger_value); 63 | } 64 | } 65 | else if (inputs_[kWait]->source->triggered) 66 | waitTrigger(inputs_[kWait]->source->trigger_value); 67 | else if (inputs_[kTrigger]->source->triggered) 68 | sendTrigger(inputs_[kTrigger]->source->trigger_offset); 69 | } 70 | 71 | LegatoFilter::LegatoFilter() : Processor(kNumInputs, kNumOutputs), 72 | last_value_(kVoiceOff) { } 73 | 74 | void LegatoFilter::process() { 75 | outputs_[kRetrigger]->clearTrigger(); 76 | outputs_[kRemain]->clearTrigger(); 77 | if (!inputs_[kTrigger]->source->triggered) 78 | return; 79 | 80 | if (inputs_[kTrigger]->source->trigger_value == kVoiceOn && 81 | last_value_ == kVoiceOn && inputs_[kLegato]->at(0)) { 82 | outputs_[kRemain]->trigger(inputs_[kTrigger]->source->trigger_value, 83 | inputs_[kTrigger]->source->trigger_offset); 84 | } 85 | else { 86 | outputs_[kRetrigger]->trigger(inputs_[kTrigger]->source->trigger_value, 87 | inputs_[kTrigger]->source->trigger_offset); 88 | } 89 | last_value_ = inputs_[kTrigger]->source->trigger_value; 90 | } 91 | 92 | PortamentoFilter::PortamentoFilter() : Processor(kNumInputs, 1), 93 | last_value_(kVoiceOff) { } 94 | 95 | void PortamentoFilter::process() { 96 | outputs_[0]->clearTrigger(); 97 | if (!inputs_[kTrigger]->source->triggered) 98 | return; 99 | 100 | int state = static_cast(inputs_[kPortamento]->at(0)); 101 | if (inputs_[kTrigger]->source->trigger_value != kVoiceOff) { 102 | if (state == kPortamentoOff || (state == kPortamentoAuto && 103 | last_value_ == kVoiceOff)) { 104 | outputs_[0]->trigger(inputs_[kTrigger]->source->trigger_value, 105 | inputs_[kTrigger]->source->trigger_offset); 106 | } 107 | } 108 | 109 | last_value_ = inputs_[kTrigger]->source->trigger_value; 110 | } 111 | } // namespace mopo 112 | -------------------------------------------------------------------------------- /mopo/src/trigger_operators.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef TRIGGER_OPERATORS_H 19 | #define TRIGGER_OPERATORS_H 20 | 21 | #include "processor.h" 22 | 23 | namespace mopo { 24 | 25 | class TriggerCombiner : public Processor { 26 | public: 27 | TriggerCombiner(); 28 | 29 | virtual Processor* clone() const { return new TriggerCombiner(*this); } 30 | 31 | void process(); 32 | }; 33 | 34 | class TriggerWait : public Processor { 35 | public: 36 | enum Inputs { 37 | kWait, 38 | kTrigger, 39 | kNumInputs 40 | }; 41 | 42 | TriggerWait(); 43 | 44 | virtual Processor* clone() const { return new TriggerWait(*this); } 45 | 46 | void process(); 47 | 48 | private: 49 | void waitTrigger(mopo_float trigger_value); 50 | void sendTrigger(int trigger_offset); 51 | 52 | bool waiting_; 53 | mopo_float trigger_value_; 54 | }; 55 | 56 | class LegatoFilter : public Processor { 57 | public: 58 | enum Inputs { 59 | kLegato, 60 | kTrigger, 61 | kNumInputs 62 | }; 63 | 64 | enum Outputs { 65 | kRetrigger, 66 | kRemain, 67 | kNumOutputs 68 | }; 69 | 70 | LegatoFilter(); 71 | 72 | virtual Processor* clone() const { return new LegatoFilter(*this); } 73 | 74 | void process(); 75 | 76 | private: 77 | mopo_float last_value_; 78 | }; 79 | 80 | class PortamentoFilter : public Processor { 81 | public: 82 | enum Inputs { 83 | kPortamento, 84 | kTrigger, 85 | kNumInputs 86 | }; 87 | 88 | enum State { 89 | kPortamentoOff, 90 | kPortamentoAuto, 91 | kPortamentoOn, 92 | kNumPortamentoStates, 93 | }; 94 | 95 | PortamentoFilter(); 96 | 97 | virtual Processor* clone() const { return new PortamentoFilter(*this); } 98 | 99 | void process(); 100 | 101 | private: 102 | mopo_float last_value_; 103 | }; 104 | } // namespace mopo 105 | 106 | #endif // TRIGGER_OPERATORS_H 107 | -------------------------------------------------------------------------------- /mopo/src/utils.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef UTILS_H 19 | #define UTILS_H 20 | 21 | #include "mopo.h" 22 | 23 | #define EPSILON 0.000000000001 24 | 25 | namespace mopo { 26 | 27 | namespace utils { 28 | 29 | inline bool closeToZero(mopo_float value) { 30 | return value <= EPSILON && value >= -EPSILON; 31 | } 32 | 33 | inline bool isSilent(const mopo_float* buffer, int length) { 34 | for (int i = 0; i < length; ++i) { 35 | if (!closeToZero(buffer[i])) 36 | return false; 37 | } 38 | return true; 39 | } 40 | } // namespace utils 41 | } // namespace mopo 42 | 43 | #endif // UTILS_H 44 | -------------------------------------------------------------------------------- /mopo/src/value.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "value.h" 18 | 19 | namespace mopo { 20 | 21 | Value::Value(mopo_float value) : Processor(kNumInputs, 1), value_(value) { 22 | for (int i = 0; i < MAX_BUFFER_SIZE; ++i) 23 | outputs_[0]->buffer[i] = value_; 24 | } 25 | 26 | void Value::process() { 27 | if (outputs_[0]->buffer[0] == value_ && 28 | outputs_[0]->buffer[buffer_size_ - 1] == value_ && 29 | !inputs_[kSet]->source->triggered) { 30 | return; 31 | } 32 | 33 | int i = 0; 34 | if (inputs_[kSet]->source->triggered) { 35 | int trigger_offset = inputs_[kSet]->source->trigger_offset; 36 | 37 | for (; i < trigger_offset; ++i) 38 | outputs_[0]->buffer[i] = value_; 39 | 40 | value_ = inputs_[kSet]->source->trigger_value; 41 | } 42 | 43 | for (; i < buffer_size_; ++i) 44 | outputs_[0]->buffer[i] = value_; 45 | } 46 | 47 | void Value::set(mopo_float value) { 48 | value_ = value; 49 | for (int i = 0; i < buffer_size_; ++i) 50 | outputs_[0]->buffer[i] = value_; 51 | } 52 | } // namespace mopo 53 | -------------------------------------------------------------------------------- /mopo/src/value.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef VALUE_H 19 | #define VALUE_H 20 | 21 | #include "processor.h" 22 | 23 | namespace mopo { 24 | 25 | class Value : public Processor { 26 | public: 27 | enum Inputs { 28 | kSet, 29 | kNumInputs 30 | }; 31 | 32 | Value(mopo_float value = 0.0); 33 | 34 | virtual Processor* clone() const { return new Value(*this); } 35 | virtual void process(); 36 | 37 | mopo_float value() const { return value_; } 38 | virtual void set(mopo_float value); 39 | 40 | protected: 41 | mopo_float value_; 42 | }; 43 | } // namespace mopo 44 | 45 | #endif // VALUE_H 46 | -------------------------------------------------------------------------------- /mopo/src/voice_handler.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef VOICE_HANDLER_H 19 | #define VOICE_HANDLER_H 20 | 21 | #include "processor_router.h" 22 | #include "value.h" 23 | 24 | #include 25 | #include 26 | 27 | namespace mopo { 28 | 29 | struct VoiceState { 30 | VoiceEvent event; 31 | mopo_float note; 32 | mopo_float velocity; 33 | }; 34 | 35 | class Voice { 36 | public: 37 | Voice(Processor* voice); 38 | 39 | Processor* processor() { return processor_; } 40 | const VoiceState* state() { return &state_; } 41 | 42 | void activate(mopo_float note, mopo_float velocity) { 43 | new_event_ = true; 44 | state_.event = kVoiceOn; 45 | state_.note = note; 46 | state_.velocity = velocity; 47 | } 48 | 49 | void deactivate() { 50 | new_event_ = true; 51 | state_.event = kVoiceOff; 52 | } 53 | 54 | bool hasNewEvent() { 55 | return new_event_; 56 | } 57 | 58 | void clearEvent() { 59 | new_event_ = false; 60 | } 61 | 62 | private: 63 | bool new_event_; 64 | VoiceState state_; 65 | Processor* processor_; 66 | }; 67 | 68 | class VoiceHandler : public Processor { 69 | public: 70 | enum Inputs { 71 | kPolyphony, 72 | kNumInputs 73 | }; 74 | 75 | VoiceHandler(size_t polyphony = 1); 76 | 77 | virtual Processor* clone() const { MOPO_ASSERT(false); return NULL; } 78 | virtual void process(); 79 | virtual void setSampleRate(int sample_rate); 80 | virtual void setBufferSize(int buffer_size); 81 | 82 | void noteOn(mopo_float note, mopo_float velocity = 1); 83 | void noteOff(mopo_float note); 84 | void sustainOn(); 85 | void sustainOff(); 86 | 87 | Output* voice_event() { return &voice_event_; } 88 | Output* note() { return ¬e_; } 89 | Output* velocity() { return &velocity_; } 90 | 91 | void addProcessor(Processor* processor); 92 | void addGlobalProcessor(Processor* processor); 93 | 94 | void setPolyphony(size_t polyphony); 95 | 96 | void setVoiceOutput(const Output* output) { 97 | voice_output_ = output; 98 | } 99 | void setVoiceOutput(const Processor* output) { 100 | setVoiceOutput(output->output()); 101 | } 102 | void setVoiceKiller(const Output* killer) { 103 | voice_killer_ = killer; 104 | } 105 | void setVoiceKiller(const Processor* killer) { 106 | setVoiceKiller(killer->output()); 107 | } 108 | 109 | private: 110 | Voice* createVoice(); 111 | void prepareVoiceTriggers(Voice* voice); 112 | void processVoice(Voice* voice); 113 | 114 | size_t polyphony_; 115 | bool sustain_; 116 | const Output* voice_output_; 117 | const Output* voice_killer_; 118 | Output voice_event_; 119 | Output note_; 120 | Output velocity_; 121 | 122 | std::list pressed_notes_; 123 | std::set all_voices_; 124 | std::list free_voices_; 125 | std::list sustained_voices_; 126 | std::list active_voices_; 127 | 128 | ProcessorRouter voice_router_; 129 | ProcessorRouter global_router_; 130 | }; 131 | } // namespace mopo 132 | 133 | #endif // VOICE_HANDLER_H 134 | -------------------------------------------------------------------------------- /mopo/src/wave.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * mopo is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * mopo is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with mopo. If not, see . 15 | */ 16 | 17 | #include "wave.h" 18 | 19 | namespace mopo { 20 | 21 | const WaveLookup Wave::lookup_; 22 | } // namespace mopo 23 | -------------------------------------------------------------------------------- /patches/bit_sin.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.890625, 3 | "amp decay": 0.679688, 4 | "amp release": 0.534376, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 81.171875, 8 | "delay dry/wet": 0.421875, 9 | "delay feedback": -0.518750, 10 | "delay time": 0.706094, 11 | "fil attack": 0, 12 | "fil decay": 0.093750, 13 | "fil env depth": 0, 14 | "fil release": 3, 15 | "fil sustain": 0.601562, 16 | "filter type": 0, 17 | "keytrack": 1, 18 | "legato": 0, 19 | "lfo 1 frequency": 10, 20 | "lfo 1 waveform": 2, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 4, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.500000, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 3, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 0, 39 | "osc 2 transpose": 24, 40 | "osc 2 tune": 0.345625, 41 | "osc 2 waveform": 0, 42 | "osc mix": 0.445313, 43 | "pitch bend range": 4, 44 | "polyphony": 12, 45 | "portamento": 0.027188, 46 | "portamento type": 0, 47 | "resonance": 0.500000, 48 | "velocity track": 0.300000, 49 | "volume": 0.554688 50 | } -------------------------------------------------------------------------------- /patches/bwang.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0, 3 | "amp decay": 2.153125, 4 | "amp release": 0.300000, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 46.367188, 8 | "delay dry/wet": 0.182812, 9 | "delay feedback": -0.253125, 10 | "delay time": 0.137344, 11 | "fil attack": 0, 12 | "fil decay": 2.175000, 13 | "fil env depth": 42, 14 | "fil release": 0.159375, 15 | "fil sustain": 0.281250, 16 | "filter type": 0, 17 | "keytrack": 0.609375, 18 | "legato": 0, 19 | "lfo 1 frequency": 2, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 0, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.010000, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 0, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 5, 39 | "osc 2 transpose": -12, 40 | "osc 2 tune": 0.173750, 41 | "osc 2 waveform": 7, 42 | "osc mix": 0.484375, 43 | "pitch bend range": 2, 44 | "polyphony": 17, 45 | "portamento": 0.010000, 46 | "portamento type": 0, 47 | "resonance": 7.984375, 48 | "velocity track": 0.300000, 49 | "volume": 0.232813 50 | } -------------------------------------------------------------------------------- /patches/default.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.010000, 3 | "amp decay": 0.700000, 4 | "amp release": 0.300000, 5 | "amp sustain": 0, 6 | "cross modulation": 0.000000, 7 | "cutoff": 92, 8 | "delay dry/wet": 0.300000, 9 | "delay feedback": -0.300000, 10 | "delay time": 0.060000, 11 | "fil attack": 0, 12 | "fil decay": 0.300000, 13 | "fil env depth": 12, 14 | "fil release": 0.300000, 15 | "fil sustain": 0, 16 | "filter type": 0, 17 | "keytrack": 0, 18 | "legato": 0, 19 | "lfo 1 frequency": 2, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 0, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.010000, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 0, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 3, 39 | "osc 2 transpose": -12, 40 | "osc 2 tune": 0.080000, 41 | "osc 2 waveform": 3, 42 | "osc mix": 0.500000, 43 | "pitch bend range": 2, 44 | "polyphony": 1, 45 | "portamento": 0.010000, 46 | "portamento type": 0, 47 | "resonance": 3, 48 | "velocity track": 0.300000, 49 | "volume": 0.600000 50 | } 51 | -------------------------------------------------------------------------------- /patches/loaded_room.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.010000, 3 | "amp decay": 2.437500, 4 | "amp release": 0.300000, 5 | "amp sustain": 0, 6 | "cross modulation": 0.189063, 7 | "cutoff": 80.593750, 8 | "delay dry/wet": 0.500000, 9 | "delay feedback": -0.503125, 10 | "delay time": 0.149219, 11 | "fil attack": 0, 12 | "fil decay": 2.835938, 13 | "fil env depth": 48, 14 | "fil release": 0.300000, 15 | "fil sustain": 0, 16 | "filter type": 0, 17 | "keytrack": 0, 18 | "legato": 0, 19 | "lfo 1 frequency": 8.953125, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2.031250, 22 | "lfo 2 waveform": 2, 23 | "mod destination 1": 3, 24 | "mod destination 2": 2, 25 | "mod destination 3": 4, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.718750, 29 | "mod scale 2": 0.135000, 30 | "mod scale 3": 0.500000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 3, 34 | "mod source 2": 3, 35 | "mod source 3": 4, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 6, 39 | "osc 2 transpose": -12, 40 | "osc 2 tune": 0.080000, 41 | "osc 2 waveform": 7, 42 | "osc mix": 0.375000, 43 | "pitch bend range": 2, 44 | "polyphony": 10, 45 | "portamento": 0.010000, 46 | "portamento type": 0, 47 | "resonance": 3.445312, 48 | "velocity track": 0.300000, 49 | "volume": 0.279688 50 | } -------------------------------------------------------------------------------- /patches/test_patch1.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.408438, 3 | "amp decay": 0.723437, 4 | "amp release": 0.229688, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 63.382812, 8 | "delay dry/wet": 0.300000, 9 | "delay feedback": -0.409375, 10 | "delay time": 0.060000, 11 | "fil attack": 0.468750, 12 | "fil decay": 0.300000, 13 | "fil env depth": 46, 14 | "fil release": 0.300000, 15 | "fil sustain": 0, 16 | "filter type": 0, 17 | "keytrack": 0, 18 | "legato": 0, 19 | "lfo 1 frequency": 2, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 0, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.010000, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 0, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 4, 39 | "osc 2 transpose": -12, 40 | "osc 2 tune": 0.080000, 41 | "osc 2 waveform": 4, 42 | "osc mix": 0.500000, 43 | "pitch bend range": 2, 44 | "polyphony": 12, 45 | "portamento": 0.010000, 46 | "portamento type": 0, 47 | "resonance": 4.359375, 48 | "velocity track": 0.300000, 49 | "volume": 0.404688 50 | } -------------------------------------------------------------------------------- /patches/test_patch2.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0, 3 | "amp decay": 0.160937, 4 | "amp release": 0.229688, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 63.382812, 8 | "delay dry/wet": 0.675000, 9 | "delay feedback": -0.596875, 10 | "delay time": 0.353906, 11 | "fil attack": 0, 12 | "fil decay": 0.159375, 13 | "fil env depth": 46, 14 | "fil release": 0.300000, 15 | "fil sustain": 0, 16 | "filter type": 0, 17 | "keytrack": 0, 18 | "legato": 0, 19 | "lfo 1 frequency": 2, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 0, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.010000, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 0, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 4, 39 | "osc 2 transpose": 12, 40 | "osc 2 tune": 0.345625, 41 | "osc 2 waveform": 4, 42 | "osc mix": 0.500000, 43 | "pitch bend range": 2, 44 | "polyphony": 12, 45 | "portamento": 0.010000, 46 | "portamento type": 0, 47 | "resonance": 4.359375, 48 | "velocity track": 0.300000, 49 | "volume": 0.584375 50 | } -------------------------------------------------------------------------------- /patches/water_wobble.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.281250, 3 | "amp decay": 1.262500, 4 | "amp release": 0.300000, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 56.421875, 8 | "delay dry/wet": 0.401562, 9 | "delay feedback": -0.612500, 10 | "delay time": 0.060000, 11 | "fil attack": 0, 12 | "fil decay": 2.175000, 13 | "fil env depth": 34, 14 | "fil release": 0.159375, 15 | "fil sustain": 0.281250, 16 | "filter type": 0, 17 | "keytrack": 0.390625, 18 | "legato": 0, 19 | "lfo 1 frequency": 8.015625, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 6.328125, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 2, 24 | "mod destination 2": 5, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.166250, 29 | "mod scale 2": 0.437500, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 3, 34 | "mod source 2": 4, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 4, 39 | "osc 2 transpose": 7, 40 | "osc 2 tune": 0.298750, 41 | "osc 2 waveform": 6, 42 | "osc mix": 0.484375, 43 | "pitch bend range": 2, 44 | "polyphony": 17, 45 | "portamento": 0.010000, 46 | "portamento type": 0, 47 | "resonance": 7.531250, 48 | "velocity track": 0.300000, 49 | "volume": 0.154688 50 | } -------------------------------------------------------------------------------- /patches/whistle.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.117188, 3 | "amp decay": 0.957812, 4 | "amp release": 0.534376, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 76.531250, 8 | "delay dry/wet": 1.416312e-12, 9 | "delay feedback": -0.596875, 10 | "delay time": 0.168281, 11 | "fil attack": 0, 12 | "fil decay": 0.093750, 13 | "fil env depth": 0, 14 | "fil release": 3, 15 | "fil sustain": 0.601562, 16 | "filter type": 0, 17 | "keytrack": 1, 18 | "legato": 0, 19 | "lfo 1 frequency": 5.359375, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 1, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.010000, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 3, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 11, 39 | "osc 2 transpose": 0, 40 | "osc 2 tune": 0.345625, 41 | "osc 2 waveform": 11, 42 | "osc mix": 0.242188, 43 | "pitch bend range": 2, 44 | "polyphony": 13, 45 | "portamento": 0.027188, 46 | "portamento type": 0, 47 | "resonance": 15, 48 | "velocity track": 0.300000, 49 | "volume": 0.576563 50 | } -------------------------------------------------------------------------------- /patches/whoooo.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.164063, 3 | "amp decay": 2.320312, 4 | "amp release": 0.534376, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 81.171875, 8 | "delay dry/wet": 1.416332e-12, 9 | "delay feedback": -0.596875, 10 | "delay time": 0.404453, 11 | "fil attack": 0, 12 | "fil decay": 0.093750, 13 | "fil env depth": 0, 14 | "fil release": 3, 15 | "fil sustain": 0.601562, 16 | "filter type": 0, 17 | "keytrack": 1, 18 | "legato": 0, 19 | "lfo 1 frequency": 5.359375, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 4, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.056875, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 3, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 0, 39 | "osc 2 transpose": 24, 40 | "osc 2 tune": 0.345625, 41 | "osc 2 waveform": 0, 42 | "osc mix": 0.445313, 43 | "pitch bend range": 4, 44 | "polyphony": 12, 45 | "portamento": 0.027188, 46 | "portamento type": 0, 47 | "resonance": 0.500000, 48 | "velocity track": 0.300000, 49 | "volume": 0.515625 50 | } -------------------------------------------------------------------------------- /patches/womp.mite: -------------------------------------------------------------------------------- 1 | { 2 | "amp attack": 0.197500, 3 | "amp decay": 0.700000, 4 | "amp release": 0.300000, 5 | "amp sustain": 0, 6 | "cross modulation": 0, 7 | "cutoff": 57.968750, 8 | "delay dry/wet": 0.401562, 9 | "delay feedback": -0.612500, 10 | "delay time": 0.137344, 11 | "fil attack": 0.445312, 12 | "fil decay": 2.175000, 13 | "fil env depth": 34, 14 | "fil release": 0.159375, 15 | "fil sustain": 0.281250, 16 | "filter type": 0, 17 | "keytrack": 0, 18 | "legato": 0, 19 | "lfo 1 frequency": 2, 20 | "lfo 1 waveform": 0, 21 | "lfo 2 frequency": 2, 22 | "lfo 2 waveform": 0, 23 | "mod destination 1": 0, 24 | "mod destination 2": 0, 25 | "mod destination 3": 0, 26 | "mod destination 4": 0, 27 | "mod destination 5": 0, 28 | "mod scale 1": 0.010000, 29 | "mod scale 2": 0.010000, 30 | "mod scale 3": 0.010000, 31 | "mod scale 4": 0.010000, 32 | "mod scale 5": 0.010000, 33 | "mod source 1": 0, 34 | "mod source 2": 0, 35 | "mod source 3": 0, 36 | "mod source 4": 0, 37 | "mod source 5": 0, 38 | "osc 1 waveform": 5, 39 | "osc 2 transpose": 19, 40 | "osc 2 tune": 0.173750, 41 | "osc 2 waveform": 5, 42 | "osc mix": 0.484375, 43 | "pitch bend range": 2, 44 | "polyphony": 17, 45 | "portamento": 0.010000, 46 | "portamento type": 0, 47 | "resonance": 3, 48 | "velocity track": 0.300000, 49 | "volume": 0.271875 50 | } -------------------------------------------------------------------------------- /po/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | 4 | # Except these files 5 | !.gitignore 6 | 7 | !ChangeLog 8 | !LINGUAS 9 | !POTFILES.in 10 | !Makevars 11 | 12 | !*.po 13 | -------------------------------------------------------------------------------- /po/Makevars: -------------------------------------------------------------------------------- 1 | # Makefile variables for PO directory in any package using GNU gettext. 2 | 3 | # Usually the message domain is the same as the package name. 4 | DOMAIN = $(PACKAGE) 5 | 6 | # These two variables depend on the location of this directory. 7 | subdir = po 8 | top_builddir = .. 9 | 10 | # These options get passed to xgettext. 11 | XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ 12 | 13 | # This is the copyright holder that gets inserted into the header of the 14 | # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding 15 | # package. (Note that the msgstr strings, extracted from the package's 16 | # sources, belong to the copyright holder of the package.) Translators are 17 | # expected to transfer the copyright for their translations to this person 18 | # or entity, or to disclaim their copyright. The empty string stands for 19 | # the public domain; in this case the translators are expected to disclaim 20 | # their copyright. 21 | COPYRIGHT_HOLDER = Matt Tytel 22 | 23 | # This is the email address or URL to which the translators shall report 24 | # bugs in the untranslated strings: 25 | # - Strings which are not entire sentences, see the maintainer guidelines 26 | # in the GNU gettext documentation, section 'Preparing Strings'. 27 | # - Strings which use unclear terms or require additional context to be 28 | # understood. 29 | # - Strings which make invalid assumptions about notation of date, time or 30 | # money. 31 | # - Pluralisation problems. 32 | # - Incorrect English spelling. 33 | # - Incorrect formatting. 34 | # It can be your email address, or a mailing list address where translators 35 | # can write to without being subscribed, or the URL of a web page through 36 | # which the translators can contact you. 37 | MSGID_BUGS_ADDRESS = matthewtytel@gmail.com 38 | 39 | # This is the list of locale categories, beyond LC_MESSAGES, for which the 40 | # message catalogs shall be used. It is usually empty. 41 | EXTRA_LOCALE_CATEGORIES = 42 | 43 | # This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' 44 | # context. Possible values are "yes" and "no". Set this to yes if the 45 | # package uses functions taking also a message context, like pgettext(), or 46 | # if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. 47 | USE_MSGCTXT = no 48 | 49 | # These options get passed to msgmerge. 50 | # Useful options are in particular: 51 | # --previous to keep previous msgids of translated messages, 52 | # --quiet to reduce the verbosity. 53 | MSGMERGE_OPTIONS = 54 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files which contain translatable strings. 2 | src/cursynth_gui.cpp 3 | -------------------------------------------------------------------------------- /rtaudio/.gitignore: -------------------------------------------------------------------------------- 1 | librtaudio.so* 2 | librtaudio.dylib.4 3 | rtaudio-config 4 | librtaudio.pc 5 | -------------------------------------------------------------------------------- /rtaudio/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LIBRARIES = librtaudio.a 2 | librtaudio_a_SOURCES = RtAudio.cpp RtAudio.h RtError.h 3 | -------------------------------------------------------------------------------- /rtaudio/RtError.h: -------------------------------------------------------------------------------- 1 | /************************************************************************/ 2 | /*! \class RtError 3 | \brief Exception handling class for RtAudio & RtMidi. 4 | 5 | The RtError class is quite simple but it does allow errors to be 6 | "caught" by RtError::Type. See the RtAudio and RtMidi 7 | documentation to know which methods can throw an RtError. 8 | 9 | */ 10 | /************************************************************************/ 11 | 12 | #ifndef RTERROR_H 13 | #define RTERROR_H 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | class RtError : public std::exception 20 | { 21 | public: 22 | //! Defined RtError types. 23 | enum Type { 24 | WARNING, /*!< A non-critical error. */ 25 | DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ 26 | UNSPECIFIED, /*!< The default, unspecified error type. */ 27 | NO_DEVICES_FOUND, /*!< No devices found on system. */ 28 | INVALID_DEVICE, /*!< An invalid device ID was specified. */ 29 | MEMORY_ERROR, /*!< An error occured during memory allocation. */ 30 | INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ 31 | INVALID_USE, /*!< The function was called incorrectly. */ 32 | DRIVER_ERROR, /*!< A system driver error occured. */ 33 | SYSTEM_ERROR, /*!< A system error occured. */ 34 | THREAD_ERROR /*!< A thread error occured. */ 35 | }; 36 | 37 | //! The constructor. 38 | RtError( const std::string& message, Type type = RtError::UNSPECIFIED ) throw() : message_(message), type_(type) {} 39 | 40 | //! The destructor. 41 | virtual ~RtError( void ) throw() {} 42 | 43 | //! Prints thrown error message to stderr. 44 | virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } 45 | 46 | //! Returns the thrown error message type. 47 | virtual const Type& getType(void) const throw() { return type_; } 48 | 49 | //! Returns the thrown error message string. 50 | virtual const std::string& getMessage(void) const throw() { return message_; } 51 | 52 | //! Returns the thrown error message as a c-style string. 53 | virtual const char* what( void ) const throw() { return message_.c_str(); } 54 | 55 | protected: 56 | std::string message_; 57 | Type type_; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /rtaudio/contrib/python/pyrtaudio/PyRtAudioTest.py: -------------------------------------------------------------------------------- 1 | 2 | import rtaudio as rt 3 | 4 | from math import cos 5 | 6 | import struct 7 | 8 | 9 | class audio_generator: 10 | def __init__(self): 11 | self.idx = -1 12 | self.freq = 440. 13 | def __call__(self): 14 | self.idx += 1 15 | if self.idx%48000 == 0: 16 | self.freq *= 2**(1/12.) 17 | return 0.5*cos(2.*3.1416*self.freq*self.idx/48000.) 18 | 19 | 20 | class callback: 21 | def __init__(self, gen): 22 | self.gen = gen 23 | self.i = 0 24 | def __call__(self,playback, capture): 25 | [struct.pack_into("f", playback, 4*o, self.gen()) for o in xrange(256)] 26 | self.i = self.i + 256 27 | if self.i > 48000*10: 28 | print '.' 29 | return 1 30 | 31 | dac = rt.RtAudio() 32 | 33 | n = dac.getDeviceCount() 34 | print 'Number of devices available: ', n 35 | 36 | for i in range(n): 37 | try: 38 | print dac.getDeviceInfo(i) 39 | except rt.RtError as e: 40 | print e 41 | 42 | 43 | print 'Default output device: ', dac.getDefaultOutputDevice() 44 | print 'Default input device: ', dac.getDefaultInputDevice() 45 | 46 | print 'is stream open: ', dac.isStreamOpen() 47 | print 'is stream running: ', dac.isStreamRunning() 48 | 49 | oParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0} 50 | iParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0} 51 | 52 | try: 53 | dac.openStream(oParams,oParams,48000,256,callback(audio_generator()) ) 54 | except rt.RtError as e: 55 | print e 56 | else: 57 | dac.startStream() 58 | 59 | import time 60 | print 'latency: ', dac.getStreamLatency() 61 | 62 | while (dac.isStreamRunning()): 63 | time.sleep(0.1) 64 | 65 | print dac.getStreamTime() 66 | 67 | dac.stopStream() 68 | dac.abortStream() 69 | dac.closeStream() 70 | 71 | -------------------------------------------------------------------------------- /rtaudio/contrib/python/pyrtaudio/readme: -------------------------------------------------------------------------------- 1 | PyRtAudio - a python wrapper around RtAudio that allows to perform audio i/o operations in real-time from the python language. 2 | 3 | By Antoine Lefebvre, 2011 4 | 5 | This software is in the development stage. Do not expect compatibility 6 | with future versions. Comments, suggestions, new features, bug fixes, 7 | etc. are welcome. 8 | 9 | 10 | This distribution of PyRtAudio contains the following: 11 | 12 | - rtaudiomodule.cpp: the python wrapper code 13 | - setup.py: a setup script use to compile and install PyRtAudio 14 | - examples: a single PyRtAudioTest.py script 15 | 16 | INSTALLATION 17 | 18 | The compilation and installation of the PyRtAudio module is handled by 19 | the python Distribution Utilities ("Distutils"). Provided that your 20 | system has a C++ compiler and is properly configure, the following 21 | command should be sufficient: 22 | 23 | >> python setup.py install 24 | 25 | Please refer to the distutils documentation for installation problems: http://docs.python.org/distutils/index.html 26 | 27 | LEGAL AND ETHICAL: 28 | 29 | The PyRtAudio license is the same as the RtAudio license: 30 | 31 | PyRtAudio: a python wrapper around RtAudio 32 | Copyright (c)2011 Antoine Lefebvre 33 | 34 | Permission is hereby granted, free of charge, to any person 35 | obtaining a copy of this software and associated documentation files 36 | (the "Software"), to deal in the Software without restriction, 37 | including without limitation the rights to use, copy, modify, merge, 38 | publish, distribute, sublicense, and/or sell copies of the Software, 39 | and to permit persons to whom the Software is furnished to do so, 40 | subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be 43 | included in all copies or substantial portions of the Software. 44 | 45 | Any person wishing to distribute modifications to the Software is 46 | asked to send the modifications to the original developer so that 47 | they can be incorporated into the canonical version. This is, 48 | however, not a binding provision of this license. 49 | 50 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 51 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 52 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 53 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 54 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 55 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 56 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 57 | 58 | -------------------------------------------------------------------------------- /rtaudio/contrib/python/pyrtaudio/setup.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python 2 | 3 | import os 4 | from distutils.core import setup, Extension 5 | 6 | if hasattr(os, 'uname'): 7 | OSNAME = os.uname()[0] 8 | else: 9 | OSNAME = 'Windows' 10 | 11 | 12 | define_macros = [] 13 | libraries = [] 14 | extra_link_args = [] 15 | extra_compile_args = ['-I../../../'] 16 | sources = ['rtaudiomodule.cpp', '../../../RtAudio.cpp'] 17 | 18 | 19 | if OSNAME == 'Linux': 20 | define_macros=[("__LINUX_ALSA__", ''), 21 | ('__LINUX_JACK__', ''), 22 | ('__LINUX_OSS__', '')] 23 | libraries = ['asound', 'jack', 'pthread'] 24 | 25 | elif OSNAME == 'Darwin': 26 | define_macros = [('__MACOSX_CORE__', '')] 27 | libraries = ['pthread', 'stdc++'] 28 | extra_link_args = ['-framework', 'CoreAudio'] 29 | 30 | elif OSNAME == 'Windows': 31 | define_macros = [('__WINDOWS_DS__', None), 32 | ('__WINDOWS_ASIO__', None), 33 | ('__LITTLE_ENDIAN__',None), 34 | ('WIN32',None)] 35 | libraries = ['winmm', 'dsound', 'Advapi32','Ole32','User32'] 36 | sources += ['../../../include/asio.cpp', 37 | '../../../include/asiodrivers.cpp', 38 | '../../../include/asiolist.cpp', 39 | '../../../include/iasiothiscallresolver.cpp'] 40 | extra_compile_args.append('-I../../../include/') 41 | extra_compile_args.append('-EHsc') 42 | 43 | 44 | 45 | audio = Extension('rtaudio', 46 | sources=sources, 47 | libraries=libraries, 48 | define_macros=define_macros, 49 | extra_compile_args = extra_compile_args, 50 | extra_link_args = extra_link_args, 51 | ) 52 | 53 | 54 | setup(name = 'rtaudio', 55 | version = '0.1', 56 | description = 'Python RtAudio interface', 57 | ext_modules = [audio]) 58 | 59 | -------------------------------------------------------------------------------- /rtaudio/include/asiodrivers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "asiodrivers.h" 3 | 4 | AsioDrivers* asioDrivers = 0; 5 | 6 | bool loadAsioDriver(char *name); 7 | 8 | bool loadAsioDriver(char *name) 9 | { 10 | if(!asioDrivers) 11 | asioDrivers = new AsioDrivers(); 12 | if(asioDrivers) 13 | return asioDrivers->loadDriver(name); 14 | return false; 15 | } 16 | 17 | //------------------------------------------------------------------------------------ 18 | 19 | #if MAC 20 | 21 | bool resolveASIO(unsigned long aconnID); 22 | 23 | AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio') 24 | { 25 | connID = -1; 26 | curIndex = -1; 27 | } 28 | 29 | AsioDrivers::~AsioDrivers() 30 | { 31 | removeCurrentDriver(); 32 | } 33 | 34 | bool AsioDrivers::getCurrentDriverName(char *name) 35 | { 36 | if(curIndex >= 0) 37 | return getName(curIndex, name); 38 | return false; 39 | } 40 | 41 | long AsioDrivers::getDriverNames(char **names, long maxDrivers) 42 | { 43 | for(long i = 0; i < getNumFragments() && i < maxDrivers; i++) 44 | getName(i, names[i]); 45 | return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers; 46 | } 47 | 48 | bool AsioDrivers::loadDriver(char *name) 49 | { 50 | char dname[64]; 51 | unsigned long newID; 52 | 53 | for(long i = 0; i < getNumFragments(); i++) 54 | { 55 | if(getName(i, dname) && !strcmp(name, dname)) 56 | { 57 | if(newInstance(i, &newID)) 58 | { 59 | if(resolveASIO(newID)) 60 | { 61 | if(connID != -1) 62 | removeInstance(curIndex, connID); 63 | curIndex = i; 64 | connID = newID; 65 | return true; 66 | } 67 | } 68 | break; 69 | } 70 | } 71 | return false; 72 | } 73 | 74 | void AsioDrivers::removeCurrentDriver() 75 | { 76 | if(connID != -1) 77 | removeInstance(curIndex, connID); 78 | connID = -1; 79 | curIndex = -1; 80 | } 81 | 82 | //------------------------------------------------------------------------------------ 83 | 84 | #elif WINDOWS 85 | 86 | #include "iasiodrv.h" 87 | 88 | extern IASIO* theAsioDriver; 89 | 90 | AsioDrivers::AsioDrivers() : AsioDriverList() 91 | { 92 | curIndex = -1; 93 | } 94 | 95 | AsioDrivers::~AsioDrivers() 96 | { 97 | } 98 | 99 | bool AsioDrivers::getCurrentDriverName(char *name) 100 | { 101 | if(curIndex >= 0) 102 | return asioGetDriverName(curIndex, name, 32) == 0 ? true : false; 103 | name[0] = 0; 104 | return false; 105 | } 106 | 107 | long AsioDrivers::getDriverNames(char **names, long maxDrivers) 108 | { 109 | for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++) 110 | asioGetDriverName(i, names[i], 32); 111 | return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers; 112 | } 113 | 114 | bool AsioDrivers::loadDriver(char *name) 115 | { 116 | char dname[64]; 117 | char curName[64]; 118 | 119 | for(long i = 0; i < asioGetNumDev(); i++) 120 | { 121 | if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname)) 122 | { 123 | curName[0] = 0; 124 | getCurrentDriverName(curName); // in case we fail... 125 | removeCurrentDriver(); 126 | 127 | if(!asioOpenDriver(i, (void **)&theAsioDriver)) 128 | { 129 | curIndex = i; 130 | return true; 131 | } 132 | else 133 | { 134 | theAsioDriver = 0; 135 | if(curName[0] && strcmp(dname, curName)) 136 | loadDriver(curName); // try restore 137 | } 138 | break; 139 | } 140 | } 141 | return false; 142 | } 143 | 144 | void AsioDrivers::removeCurrentDriver() 145 | { 146 | if(curIndex != -1) 147 | asioCloseDriver(curIndex); 148 | curIndex = -1; 149 | } 150 | 151 | #elif SGI || BEOS 152 | 153 | #include "asiolist.h" 154 | 155 | AsioDrivers::AsioDrivers() 156 | : AsioDriverList() 157 | { 158 | curIndex = -1; 159 | } 160 | 161 | AsioDrivers::~AsioDrivers() 162 | { 163 | } 164 | 165 | bool AsioDrivers::getCurrentDriverName(char *name) 166 | { 167 | return false; 168 | } 169 | 170 | long AsioDrivers::getDriverNames(char **names, long maxDrivers) 171 | { 172 | return 0; 173 | } 174 | 175 | bool AsioDrivers::loadDriver(char *name) 176 | { 177 | return false; 178 | } 179 | 180 | void AsioDrivers::removeCurrentDriver() 181 | { 182 | } 183 | 184 | #else 185 | #error implement me 186 | #endif 187 | -------------------------------------------------------------------------------- /rtaudio/include/asiodrivers.h: -------------------------------------------------------------------------------- 1 | #ifndef __AsioDrivers__ 2 | #define __AsioDrivers__ 3 | 4 | #include "ginclude.h" 5 | 6 | #if MAC 7 | #include "CodeFragments.hpp" 8 | 9 | class AsioDrivers : public CodeFragments 10 | 11 | #elif WINDOWS 12 | #include 13 | #include "asiolist.h" 14 | 15 | class AsioDrivers : public AsioDriverList 16 | 17 | #elif SGI || BEOS 18 | #include "asiolist.h" 19 | 20 | class AsioDrivers : public AsioDriverList 21 | 22 | #else 23 | #error implement me 24 | #endif 25 | 26 | { 27 | public: 28 | AsioDrivers(); 29 | ~AsioDrivers(); 30 | 31 | bool getCurrentDriverName(char *name); 32 | long getDriverNames(char **names, long maxDrivers); 33 | bool loadDriver(char *name); 34 | void removeCurrentDriver(); 35 | long getCurrentDriverIndex() {return curIndex;} 36 | protected: 37 | unsigned long connID; 38 | long curIndex; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /rtaudio/include/asiodrvr.h: -------------------------------------------------------------------------------- 1 | /* 2 | Steinberg Audio Stream I/O API 3 | (c) 1996, Steinberg Soft- und Hardware GmbH 4 | charlie (May 1996) 5 | 6 | asiodrvr.h 7 | c++ superclass to implement asio functionality. from this, 8 | you can derive whatever required 9 | */ 10 | 11 | #ifndef _asiodrvr_ 12 | #define _asiodrvr_ 13 | 14 | // cpu and os system we are running on 15 | #include "asiosys.h" 16 | // basic "C" interface 17 | #include "asio.h" 18 | 19 | class AsioDriver; 20 | extern AsioDriver *getDriver(); // for generic constructor 21 | 22 | #if WINDOWS 23 | #include 24 | #include "combase.h" 25 | #include "iasiodrv.h" 26 | class AsioDriver : public IASIO ,public CUnknown 27 | { 28 | public: 29 | AsioDriver(LPUNKNOWN pUnk, HRESULT *phr); 30 | 31 | DECLARE_IUNKNOWN 32 | // Factory method 33 | static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr); 34 | // IUnknown 35 | virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject); 36 | 37 | #else 38 | 39 | class AsioDriver 40 | { 41 | public: 42 | AsioDriver(); 43 | #endif 44 | virtual ~AsioDriver(); 45 | 46 | virtual ASIOBool init(void* sysRef); 47 | virtual void getDriverName(char *name); // max 32 bytes incl. terminating zero 48 | virtual long getDriverVersion(); 49 | virtual void getErrorMessage(char *string); // max 124 bytes incl. 50 | 51 | virtual ASIOError start(); 52 | virtual ASIOError stop(); 53 | 54 | virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels); 55 | virtual ASIOError getLatencies(long *inputLatency, long *outputLatency); 56 | virtual ASIOError getBufferSize(long *minSize, long *maxSize, 57 | long *preferredSize, long *granularity); 58 | 59 | virtual ASIOError canSampleRate(ASIOSampleRate sampleRate); 60 | virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate); 61 | virtual ASIOError setSampleRate(ASIOSampleRate sampleRate); 62 | virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources); 63 | virtual ASIOError setClockSource(long reference); 64 | 65 | virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp); 66 | virtual ASIOError getChannelInfo(ASIOChannelInfo *info); 67 | 68 | virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, 69 | long bufferSize, ASIOCallbacks *callbacks); 70 | virtual ASIOError disposeBuffers(); 71 | 72 | virtual ASIOError controlPanel(); 73 | virtual ASIOError future(long selector, void *opt); 74 | virtual ASIOError outputReady(); 75 | }; 76 | #endif 77 | -------------------------------------------------------------------------------- /rtaudio/include/asiolist.h: -------------------------------------------------------------------------------- 1 | #ifndef __asiolist__ 2 | #define __asiolist__ 3 | 4 | #define DRVERR -5000 5 | #define DRVERR_INVALID_PARAM DRVERR-1 6 | #define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2 7 | #define DRVERR_DEVICE_NOT_FOUND DRVERR-3 8 | 9 | #define MAXPATHLEN 512 10 | #define MAXDRVNAMELEN 128 11 | 12 | struct asiodrvstruct 13 | { 14 | int drvID; 15 | CLSID clsid; 16 | char dllpath[MAXPATHLEN]; 17 | char drvname[MAXDRVNAMELEN]; 18 | LPVOID asiodrv; 19 | struct asiodrvstruct *next; 20 | }; 21 | 22 | typedef struct asiodrvstruct ASIODRVSTRUCT; 23 | typedef ASIODRVSTRUCT *LPASIODRVSTRUCT; 24 | 25 | class AsioDriverList { 26 | public: 27 | AsioDriverList(); 28 | ~AsioDriverList(); 29 | 30 | LONG asioOpenDriver (int,VOID **); 31 | LONG asioCloseDriver (int); 32 | 33 | // nice to have 34 | LONG asioGetNumDev (VOID); 35 | LONG asioGetDriverName (int,char *,int); 36 | LONG asioGetDriverPath (int,char *,int); 37 | LONG asioGetDriverCLSID (int,CLSID *); 38 | 39 | // or use directly access 40 | LPASIODRVSTRUCT lpdrvlist; 41 | int numdrv; 42 | }; 43 | 44 | typedef class AsioDriverList *LPASIODRIVERLIST; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /rtaudio/include/asiosys.h: -------------------------------------------------------------------------------- 1 | #ifndef __asiosys__ 2 | #define __asiosys__ 3 | 4 | #ifdef WIN32 5 | #undef MAC 6 | #define PPC 0 7 | #define WINDOWS 1 8 | #define SGI 0 9 | #define SUN 0 10 | #define LINUX 0 11 | #define BEOS 0 12 | 13 | #define NATIVE_INT64 0 14 | #define IEEE754_64FLOAT 1 15 | 16 | #elif BEOS 17 | #define MAC 0 18 | #define PPC 0 19 | #define WINDOWS 0 20 | #define PC 0 21 | #define SGI 0 22 | #define SUN 0 23 | #define LINUX 0 24 | 25 | #define NATIVE_INT64 0 26 | #define IEEE754_64FLOAT 1 27 | 28 | #ifndef DEBUG 29 | #define DEBUG 0 30 | #if DEBUG 31 | void DEBUGGERMESSAGE(char *string); 32 | #else 33 | #define DEBUGGERMESSAGE(a) 34 | #endif 35 | #endif 36 | 37 | #elif SGI 38 | #define MAC 0 39 | #define PPC 0 40 | #define WINDOWS 0 41 | #define PC 0 42 | #define SUN 0 43 | #define LINUX 0 44 | #define BEOS 0 45 | 46 | #define NATIVE_INT64 0 47 | #define IEEE754_64FLOAT 1 48 | 49 | #ifndef DEBUG 50 | #define DEBUG 0 51 | #if DEBUG 52 | void DEBUGGERMESSAGE(char *string); 53 | #else 54 | #define DEBUGGERMESSAGE(a) 55 | #endif 56 | #endif 57 | 58 | #else // MAC 59 | 60 | #define MAC 1 61 | #define PPC 1 62 | #define WINDOWS 0 63 | #define PC 0 64 | #define SGI 0 65 | #define SUN 0 66 | #define LINUX 0 67 | #define BEOS 0 68 | 69 | #define NATIVE_INT64 0 70 | #define IEEE754_64FLOAT 1 71 | 72 | #ifndef DEBUG 73 | #define DEBUG 0 74 | #if DEBUG 75 | void DEBUGGERMESSAGE(char *string); 76 | #else 77 | #define DEBUGGERMESSAGE(a) 78 | #endif 79 | #endif 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /rtaudio/include/ginclude.h: -------------------------------------------------------------------------------- 1 | #ifndef __gInclude__ 2 | #define __gInclude__ 3 | 4 | #if SGI 5 | #undef BEOS 6 | #undef MAC 7 | #undef WINDOWS 8 | // 9 | #define ASIO_BIG_ENDIAN 1 10 | #define ASIO_CPU_MIPS 1 11 | #elif defined WIN32 12 | #undef BEOS 13 | #undef MAC 14 | #undef SGI 15 | #define WINDOWS 1 16 | #define ASIO_LITTLE_ENDIAN 1 17 | #define ASIO_CPU_X86 1 18 | #elif BEOS 19 | #undef MAC 20 | #undef SGI 21 | #undef WINDOWS 22 | #define ASIO_LITTLE_ENDIAN 1 23 | #define ASIO_CPU_X86 1 24 | // 25 | #else 26 | #define MAC 1 27 | #undef BEOS 28 | #undef WINDOWS 29 | #undef SGI 30 | #define ASIO_BIG_ENDIAN 1 31 | #define ASIO_CPU_PPC 1 32 | #endif 33 | 34 | // always 35 | #define NATIVE_INT64 0 36 | #define IEEE754_64FLOAT 1 37 | 38 | #endif // __gInclude__ 39 | -------------------------------------------------------------------------------- /rtaudio/include/iasiodrv.h: -------------------------------------------------------------------------------- 1 | #include "asiosys.h" 2 | #include "asio.h" 3 | 4 | /* Forward Declarations */ 5 | 6 | #ifndef __ASIODRIVER_FWD_DEFINED__ 7 | #define __ASIODRIVER_FWD_DEFINED__ 8 | typedef interface IASIO IASIO; 9 | #endif /* __ASIODRIVER_FWD_DEFINED__ */ 10 | 11 | interface IASIO : public IUnknown 12 | { 13 | 14 | virtual ASIOBool init(void *sysHandle) = 0; 15 | virtual void getDriverName(char *name) = 0; 16 | virtual long getDriverVersion() = 0; 17 | virtual void getErrorMessage(char *string) = 0; 18 | virtual ASIOError start() = 0; 19 | virtual ASIOError stop() = 0; 20 | virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0; 21 | virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0; 22 | virtual ASIOError getBufferSize(long *minSize, long *maxSize, 23 | long *preferredSize, long *granularity) = 0; 24 | virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0; 25 | virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0; 26 | virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0; 27 | virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0; 28 | virtual ASIOError setClockSource(long reference) = 0; 29 | virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0; 30 | virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0; 31 | virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, 32 | long bufferSize, ASIOCallbacks *callbacks) = 0; 33 | virtual ASIOError disposeBuffers() = 0; 34 | virtual ASIOError controlPanel() = 0; 35 | virtual ASIOError future(long selector,void *opt) = 0; 36 | virtual ASIOError outputReady() = 0; 37 | }; 38 | -------------------------------------------------------------------------------- /rtaudio/install: -------------------------------------------------------------------------------- 1 | RtAudio - a set of C++ classes which provide a common API for realtime audio input/output across GNU/Linux (native ALSA, JACK, PulseAudio, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems. 2 | 3 | By Gary P. Scavone, 2001-2013. 4 | 5 | To configure and compile (on Unix systems and MinGW): 6 | 7 | 1. Unpack the RtAudio distribution (tar -xzf rtaudio-x.x.tar.gz). 8 | 2. From within the directory containing this file, run configure: 9 | 10 | ./configure 11 | 12 | 3. Typing "make" will compile static and shared libraries. 13 | 14 | 4. From within the "tests" directory, type "make" to compile the example programs. 15 | 16 | A few options can be passed to configure, including: 17 | 18 | --enable-debug = enable various debug output 19 | --with-alsa = choose native ALSA API support (GNU/Linux only) 20 | --with-pulse = choose native PulseAudio API support (GNU/Linux only) 21 | --with-oss = choose OSS API support (GNU/Linux only) 22 | --with-jack = choose JACK server support (GNU/Linux or Macintosh OS-X) 23 | --with-core = choose CoreAudio API support (Macintosh OS-X only) 24 | --with-asio = choose ASIO API support (windows only) 25 | --with-ds = choose DirectSound API support (windows only) 26 | 27 | Typing "./configure --help" will display all the available options. Note that you can provide more than one "--with-" flag to the configure script to enable multiple API support. 28 | 29 | If you wish to use a different compiler than that selected by configure, specify that compiler in the command line (ex. to use CC): 30 | 31 | ./configure CXX=CC 32 | 33 | 34 | WINDOWS USERS: 35 | 36 | RtAudio compiles with the MinGW compiler or MS Visual Studio. 37 | 38 | Visual C++ 6.0 project files (very old) are included for the test programs in the /tests/Windows/ directory. These projects compile API support for both ASIO and DirectSound. 39 | 40 | 41 | GNU/LINUX OSS: 42 | 43 | The OSS API support in RtAudio has not been tested for many years. I'm not even sure there are OSS drivers supporting recent linux kernels. In all likelihood, the OSS API code in RtAudio will disappear within the next year or two (if you don't want this to happen, let me know). 44 | -------------------------------------------------------------------------------- /rtaudio/librtaudio.pc.in: -------------------------------------------------------------------------------- 1 | prefix=/usr/local 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: librtaudio 7 | Description: RtAudio - a set of C++ classes that provide a common API for realtime audio input/output 8 | Version: 4.0.12 9 | Requires: @req@ 10 | Libs: -L${libdir} -lrtaudio 11 | Libs.private: -lpthread 12 | Cflags: -pthread -I${includedir} @CPPFLAGS@ -------------------------------------------------------------------------------- /rtaudio/readme: -------------------------------------------------------------------------------- 1 | RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across GNU/Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems. 2 | 3 | By Gary P. Scavone, 2001-2013. 4 | 5 | This distribution of RtAudio contains the following: 6 | 7 | doc: RtAudio documentation (see doc/html/index.html) 8 | tests: example RtAudio programs 9 | include: header and source files necessary for ASIO, DS & OSS compilation 10 | tests/Windows: Visual C++ .net test program workspace and projects 11 | 12 | OVERVIEW: 13 | 14 | RtAudio is a set of C++ classes that provides a common API (Application Programming Interface) for realtime audio input/output across GNU/Linux (native ALSA, JACK, and OSS), Macintosh OS X, SGI, and Windows (DirectSound and ASIO) operating systems. RtAudio significantly simplifies the process of interacting with computer audio hardware. It was designed with the following objectives: 15 | 16 | - object-oriented C++ design 17 | - simple, common API across all supported platforms 18 | - only one source and two header files for easy inclusion in programming projects 19 | - allow simultaneous multi-api support 20 | - support dynamic connection of devices 21 | - provide extensive audio device parameter control 22 | - allow audio device capability probing 23 | - automatic internal conversion for data format, channel number compensation, (de)interleaving, and byte-swapping 24 | 25 | RtAudio incorporates the concept of audio streams, which represent audio output (playback) and/or input (recording). Available audio devices and their capabilities can be enumerated and then specified when opening a stream. Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance. See the \ref apinotes section for information specific to each of the supported audio APIs. 26 | 27 | FURTHER READING: 28 | 29 | For complete documentation on RtAudio, see the doc directory of the distribution or surf to http://www.music.mcgill.ca/~gary/rtaudio/. 30 | 31 | 32 | LEGAL AND ETHICAL: 33 | 34 | The RtAudio license is similar to the MIT License. 35 | 36 | RtAudio: a set of realtime audio i/o C++ classes 37 | Copyright (c) 2001-2013 Gary P. Scavone 38 | 39 | Permission is hereby granted, free of charge, to any person 40 | obtaining a copy of this software and associated documentation files 41 | (the "Software"), to deal in the Software without restriction, 42 | including without limitation the rights to use, copy, modify, merge, 43 | publish, distribute, sublicense, and/or sell copies of the Software, 44 | and to permit persons to whom the Software is furnished to do so, 45 | subject to the following conditions: 46 | 47 | The above copyright notice and this permission notice shall be 48 | included in all copies or substantial portions of the Software. 49 | 50 | Any person wishing to distribute modifications to the Software is 51 | asked to send the modifications to the original developer so that 52 | they can be incorporated into the canonical version. This is, 53 | however, not a binding provision of this license. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 56 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 57 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 58 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 59 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 60 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 61 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 62 | -------------------------------------------------------------------------------- /rtaudio/rtaudio-config.in: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | if (test "x$#" != "x1") ; then 3 | echo "Usage: $0 [--libs | --cxxflags | --cppflags]" 4 | exit; 5 | fi 6 | 7 | LIBRARY="@LIBS@" 8 | CXXFLAGS="@CXXFLAGS@" 9 | CPPFLAGS="@CPPFLAGS@" 10 | 11 | if (test "x$1" == "x--libs") ; then 12 | echo "$LIBRARY" 13 | elif (test "x$1" == "x--cxxflags") ; then 14 | echo "$CXXFLAGS" 15 | elif (test "x$1" == "x--cppflags") ; then 16 | echo "$CPPFLAGS" 17 | else 18 | echo "Unknown option: $1" 19 | fi 20 | -------------------------------------------------------------------------------- /rtaudio/tests/Makefile.in: -------------------------------------------------------------------------------- 1 | ### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in 2 | ### RtAudio tests Makefile - for various flavors of unix and MinGW 3 | 4 | PROGRAMS = audioprobe playsaw playraw record duplex testall teststops 5 | RM = /bin/rm 6 | SRC_PATH = .. 7 | INCLUDE = .. 8 | OBJECT_PATH = @object_path@ 9 | vpath %.o $(OBJECT_PATH) 10 | 11 | OBJECTS = RtAudio.o @objects@ 12 | 13 | CC = @CXX@ 14 | DEFS = @CPPFLAGS@ 15 | CFLAGS = @CXXFLAGS@ 16 | CFLAGS += -I$(INCLUDE) -I../include 17 | LIBRARY = @LIBS@ 18 | 19 | %.o : $(SRC_PATH)/%.cpp 20 | $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@ 21 | 22 | %.o : ../include/%.cpp 23 | $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@ 24 | 25 | all : $(PROGRAMS) 26 | 27 | audioprobe : audioprobe.cpp $(OBJECTS) 28 | $(CC) $(CFLAGS) $(DEFS) -o audioprobe audioprobe.cpp $(OBJECT_PATH)/*.o $(LIBRARY) 29 | 30 | playsaw : playsaw.cpp $(OBJECTS) 31 | $(CC) $(CFLAGS) $(DEFS) -o playsaw playsaw.cpp $(OBJECT_PATH)/*.o $(LIBRARY) 32 | 33 | playraw : playraw.cpp $(OBJECTS) 34 | $(CC) $(CFLAGS) $(DEFS) -o playraw playraw.cpp $(OBJECT_PATH)/*.o $(LIBRARY) 35 | 36 | record : record.cpp $(OBJECTS) 37 | $(CC) $(CFLAGS) $(DEFS) -o record record.cpp $(OBJECT_PATH)/*.o $(LIBRARY) 38 | 39 | duplex : duplex.cpp $(OBJECTS) 40 | $(CC) $(CFLAGS) $(DEFS) -o duplex duplex.cpp $(OBJECT_PATH)/*.o $(LIBRARY) 41 | 42 | testall : testall.cpp $(OBJECTS) 43 | $(CC) $(CFLAGS) $(DEFS) -o testall testall.cpp $(OBJECT_PATH)/*.o $(LIBRARY) 44 | 45 | teststops : teststops.cpp $(OBJECTS) 46 | $(CC) $(CFLAGS) $(DEFS) -o teststops teststops.cpp $(OBJECT_PATH)/*.o $(LIBRARY) 47 | 48 | clean : 49 | $(RM) -f $(OBJECT_PATH)/*.o 50 | $(RM) -f $(PROGRAMS) 51 | $(RM) -f *.raw *~ *.exe 52 | $(RM) -fR *.dSYM 53 | 54 | distclean: clean 55 | $(RM) -f Makefile 56 | 57 | strip : 58 | strip $(PROGRAMS) 59 | -------------------------------------------------------------------------------- /rtaudio/tests/Windows/rtaudio.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | 4 | ############################################################################### 5 | 6 | Project: "audioprobe"=.\audioprobe.dsp - Package Owner=<4> 7 | 8 | Package=<5> 9 | {{{ 10 | }}} 11 | 12 | Package=<4> 13 | {{{ 14 | }}} 15 | 16 | ############################################################################### 17 | 18 | Project: "duplex"=.\duplex.dsp - Package Owner=<4> 19 | 20 | Package=<5> 21 | {{{ 22 | }}} 23 | 24 | Package=<4> 25 | {{{ 26 | }}} 27 | 28 | ############################################################################### 29 | 30 | Project: "playraw"=.\playraw.dsp - Package Owner=<4> 31 | 32 | Package=<5> 33 | {{{ 34 | }}} 35 | 36 | Package=<4> 37 | {{{ 38 | }}} 39 | 40 | ############################################################################### 41 | 42 | Project: "playsaw"=.\playsaw.dsp - Package Owner=<4> 43 | 44 | Package=<5> 45 | {{{ 46 | }}} 47 | 48 | Package=<4> 49 | {{{ 50 | }}} 51 | 52 | ############################################################################### 53 | 54 | Project: "record"=.\record.dsp - Package Owner=<4> 55 | 56 | Package=<5> 57 | {{{ 58 | }}} 59 | 60 | Package=<4> 61 | {{{ 62 | }}} 63 | 64 | ############################################################################### 65 | 66 | Project: "testall"=.\testall.dsp - Package Owner=<4> 67 | 68 | Package=<5> 69 | {{{ 70 | }}} 71 | 72 | Package=<4> 73 | {{{ 74 | }}} 75 | 76 | ############################################################################### 77 | 78 | Project: "teststops"=.\teststops.dsp - Package Owner=<4> 79 | 80 | Package=<5> 81 | {{{ 82 | }}} 83 | 84 | Package=<4> 85 | {{{ 86 | }}} 87 | 88 | ############################################################################### 89 | 90 | Global: 91 | 92 | Package=<5> 93 | {{{ 94 | }}} 95 | 96 | Package=<3> 97 | {{{ 98 | }}} 99 | 100 | ############################################################################### 101 | 102 | -------------------------------------------------------------------------------- /rtaudio/tests/audioprobe.cpp: -------------------------------------------------------------------------------- 1 | /******************************************/ 2 | /* 3 | audioprobe.cpp 4 | by Gary P. Scavone, 2001 5 | 6 | Probe audio system and prints device info. 7 | */ 8 | /******************************************/ 9 | 10 | #include "RtAudio.h" 11 | #include 12 | #include 13 | 14 | int main() 15 | { 16 | // Create an api map. 17 | std::map apiMap; 18 | apiMap[RtAudio::MACOSX_CORE] = "OS-X Core Audio"; 19 | apiMap[RtAudio::WINDOWS_ASIO] = "Windows ASIO"; 20 | apiMap[RtAudio::WINDOWS_DS] = "Windows Direct Sound"; 21 | apiMap[RtAudio::UNIX_JACK] = "Jack Client"; 22 | apiMap[RtAudio::LINUX_ALSA] = "Linux ALSA"; 23 | apiMap[RtAudio::LINUX_PULSE] = "Linux PulseAudio"; 24 | apiMap[RtAudio::LINUX_OSS] = "Linux OSS"; 25 | apiMap[RtAudio::RTAUDIO_DUMMY] = "RtAudio Dummy"; 26 | 27 | std::vector< RtAudio::Api > apis; 28 | RtAudio :: getCompiledApi( apis ); 29 | 30 | std::cout << "\nRtAudio Version " << RtAudio::getVersion() << std::endl; 31 | 32 | std::cout << "\nCompiled APIs:\n"; 33 | for ( unsigned int i=0; i 13 | #include 14 | #include 15 | 16 | /* 17 | typedef char MY_TYPE; 18 | #define FORMAT RTAUDIO_SINT8 19 | */ 20 | 21 | typedef signed short MY_TYPE; 22 | #define FORMAT RTAUDIO_SINT16 23 | 24 | /* 25 | typedef S24 MY_TYPE; 26 | #define FORMAT RTAUDIO_SINT24 27 | 28 | typedef signed long MY_TYPE; 29 | #define FORMAT RTAUDIO_SINT32 30 | 31 | typedef float MY_TYPE; 32 | #define FORMAT RTAUDIO_FLOAT32 33 | 34 | typedef double MY_TYPE; 35 | #define FORMAT RTAUDIO_FLOAT64 36 | */ 37 | 38 | void usage( void ) { 39 | // Error function in case of incorrect command-line 40 | // argument specifications 41 | std::cout << "\nuseage: duplex N fs \n"; 42 | std::cout << " where N = number of channels,\n"; 43 | std::cout << " fs = the sample rate,\n"; 44 | std::cout << " iDevice = optional input device to use (default = 0),\n"; 45 | std::cout << " oDevice = optional output device to use (default = 0),\n"; 46 | std::cout << " iChannelOffset = an optional input channel offset (default = 0),\n"; 47 | std::cout << " and oChannelOffset = optional output channel offset (default = 0).\n\n"; 48 | exit( 0 ); 49 | } 50 | 51 | int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, 52 | double streamTime, RtAudioStreamStatus status, void *data ) 53 | { 54 | // Since the number of input and output channels is equal, we can do 55 | // a simple buffer copy operation here. 56 | if ( status ) std::cout << "Stream over/underflow detected." << std::endl; 57 | 58 | unsigned int *bytes = (unsigned int *) data; 59 | memcpy( outputBuffer, inputBuffer, *bytes ); 60 | return 0; 61 | } 62 | 63 | int main( int argc, char *argv[] ) 64 | { 65 | unsigned int channels, fs, bufferBytes, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0; 66 | 67 | // Minimal command-line checking 68 | if (argc < 3 || argc > 7 ) usage(); 69 | 70 | RtAudio adac; 71 | if ( adac.getDeviceCount() < 1 ) { 72 | std::cout << "\nNo audio devices found!\n"; 73 | exit( 1 ); 74 | } 75 | 76 | channels = (unsigned int) atoi(argv[1]); 77 | fs = (unsigned int) atoi(argv[2]); 78 | if ( argc > 3 ) 79 | iDevice = (unsigned int) atoi(argv[3]); 80 | if ( argc > 4 ) 81 | oDevice = (unsigned int) atoi(argv[4]); 82 | if ( argc > 5 ) 83 | iOffset = (unsigned int) atoi(argv[5]); 84 | if ( argc > 6 ) 85 | oOffset = (unsigned int) atoi(argv[6]); 86 | 87 | // Let RtAudio print messages to stderr. 88 | adac.showWarnings( true ); 89 | 90 | // Set the same number of channels for both input and output. 91 | unsigned int bufferFrames = 512; 92 | RtAudio::StreamParameters iParams, oParams; 93 | iParams.deviceId = iDevice; 94 | iParams.nChannels = channels; 95 | iParams.firstChannel = iOffset; 96 | oParams.deviceId = oDevice; 97 | oParams.nChannels = channels; 98 | oParams.firstChannel = oOffset; 99 | 100 | RtAudio::StreamOptions options; 101 | //options.flags |= RTAUDIO_NONINTERLEAVED; 102 | 103 | try { 104 | adac.openStream( &oParams, &iParams, FORMAT, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options ); 105 | } 106 | catch ( RtError& e ) { 107 | std::cout << '\n' << e.getMessage() << '\n' << std::endl; 108 | exit( 1 ); 109 | } 110 | 111 | bufferBytes = bufferFrames * channels * sizeof( MY_TYPE ); 112 | 113 | // Test RtAudio functionality for reporting latency. 114 | std::cout << "\nStream latency = " << adac.getStreamLatency() << " frames" << std::endl; 115 | 116 | try { 117 | adac.startStream(); 118 | 119 | char input; 120 | std::cout << "\nRunning ... press to quit (buffer frames = " << bufferFrames << ").\n"; 121 | std::cin.get(input); 122 | 123 | // Stop the stream. 124 | adac.stopStream(); 125 | } 126 | catch ( RtError& e ) { 127 | std::cout << '\n' << e.getMessage() << '\n' << std::endl; 128 | goto cleanup; 129 | } 130 | 131 | cleanup: 132 | if ( adac.isStreamOpen() ) adac.closeStream(); 133 | 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /rtaudio/tests/playraw.cpp: -------------------------------------------------------------------------------- 1 | /******************************************/ 2 | /* 3 | playraw.cpp 4 | by Gary P. Scavone, 2007 5 | 6 | Play a specified raw file. It is necessary 7 | that the file be of the same data format as 8 | defined below. 9 | */ 10 | /******************************************/ 11 | 12 | #include "RtAudio.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* 19 | typedef char MY_TYPE; 20 | #define FORMAT RTAUDIO_SINT8 21 | #define SCALE 127.0 22 | */ 23 | 24 | typedef signed short MY_TYPE; 25 | #define FORMAT RTAUDIO_SINT16 26 | #define SCALE 32767.0 27 | 28 | /* 29 | typedef S24 MY_TYPE; 30 | #define FORMAT RTAUDIO_SINT24 31 | #define SCALE 8388607.0 32 | 33 | typedef signed int MY_TYPE; 34 | #define FORMAT RTAUDIO_SINT32 35 | #define SCALE 2147483647.0 36 | 37 | typedef float MY_TYPE; 38 | #define FORMAT RTAUDIO_FLOAT32 39 | #define SCALE 1.0; 40 | 41 | typedef double MY_TYPE; 42 | #define FORMAT RTAUDIO_FLOAT64 43 | #define SCALE 1.0; 44 | */ 45 | 46 | // Platform-dependent sleep routines. 47 | #if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ ) 48 | #include 49 | #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 50 | #else // Unix variants 51 | #include 52 | #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) 53 | #endif 54 | 55 | void usage( void ) { 56 | // Error function in case of incorrect command-line 57 | // argument specifications 58 | std::cout << "\nuseage: playraw N fs file \n"; 59 | std::cout << " where N = number of channels,\n"; 60 | std::cout << " fs = the sample rate, \n"; 61 | std::cout << " file = the raw file to play,\n"; 62 | std::cout << " device = optional device to use (default = 0),\n"; 63 | std::cout << " and channelOffset = an optional channel offset on the device (default = 0).\n\n"; 64 | exit( 0 ); 65 | } 66 | 67 | struct OutputData { 68 | FILE *fd; 69 | unsigned int channels; 70 | }; 71 | 72 | // Interleaved buffers 73 | int output( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, 74 | double streamTime, RtAudioStreamStatus status, void *data ) 75 | { 76 | OutputData *oData = (OutputData*) data; 77 | 78 | // In general, it's not a good idea to do file input in the audio 79 | // callback function but I'm doing it here because I don't know the 80 | // length of the file we are reading. 81 | unsigned int count = fread( outputBuffer, oData->channels * sizeof( MY_TYPE ), nBufferFrames, oData->fd); 82 | if ( count < nBufferFrames ) { 83 | unsigned int bytes = (nBufferFrames - count) * oData->channels * sizeof( MY_TYPE ); 84 | unsigned int startByte = count * oData->channels * sizeof( MY_TYPE ); 85 | memset( (char *)(outputBuffer)+startByte, 0, bytes ); 86 | return 1; 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | int main( int argc, char *argv[] ) 93 | { 94 | unsigned int channels, fs, bufferFrames, device = 0, offset = 0; 95 | char *file; 96 | 97 | // minimal command-line checking 98 | if ( argc < 4 || argc > 6 ) usage(); 99 | 100 | RtAudio dac; 101 | if ( dac.getDeviceCount() < 1 ) { 102 | std::cout << "\nNo audio devices found!\n"; 103 | exit( 0 ); 104 | } 105 | 106 | channels = (unsigned int) atoi( argv[1]) ; 107 | fs = (unsigned int) atoi( argv[2] ); 108 | file = argv[3]; 109 | if ( argc > 4 ) 110 | device = (unsigned int) atoi( argv[4] ); 111 | if ( argc > 5 ) 112 | offset = (unsigned int) atoi( argv[5] ); 113 | 114 | OutputData data; 115 | data.fd = fopen( file, "rb" ); 116 | if ( !data.fd ) { 117 | std::cout << "Unable to find or open file!\n"; 118 | exit( 1 ); 119 | } 120 | 121 | // Set our stream parameters for output only. 122 | bufferFrames = 512; 123 | RtAudio::StreamParameters oParams; 124 | oParams.deviceId = device; 125 | oParams.nChannels = channels; 126 | oParams.firstChannel = offset; 127 | 128 | data.channels = channels; 129 | try { 130 | dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &output, (void *)&data ); 131 | dac.startStream(); 132 | } 133 | catch ( RtError& e ) { 134 | std::cout << '\n' << e.getMessage() << '\n' << std::endl; 135 | goto cleanup; 136 | } 137 | 138 | std::cout << "\nPlaying raw file " << file << " (buffer frames = " << bufferFrames << ")." << std::endl; 139 | while ( 1 ) { 140 | SLEEP( 100 ); // wake every 100 ms to check if we're done 141 | if ( dac.isStreamRunning() == false ) break; 142 | } 143 | 144 | cleanup: 145 | fclose( data.fd ); 146 | dac.closeStream(); 147 | 148 | return 0; 149 | } 150 | -------------------------------------------------------------------------------- /rtmidi/.gitignore: -------------------------------------------------------------------------------- 1 | librtmidi.so* 2 | librtmidi.dylib.4 3 | rtmidi-config 4 | librtmidi.pc 5 | -------------------------------------------------------------------------------- /rtmidi/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LIBRARIES = librtmidi.a 2 | librtmidi_a_SOURCES = RtMidi.cpp RtMidi.h RtError.h 3 | -------------------------------------------------------------------------------- /rtmidi/RtError.h: -------------------------------------------------------------------------------- 1 | /************************************************************************/ 2 | /*! \class RtError 3 | \brief Exception handling class for RtAudio & RtMidi. 4 | 5 | The RtError class is quite simple but it does allow errors to be 6 | "caught" by RtError::Type. See the RtAudio and RtMidi 7 | documentation to know which methods can throw an RtError. 8 | 9 | */ 10 | /************************************************************************/ 11 | 12 | #ifndef RTERROR_H 13 | #define RTERROR_H 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | class RtError : public std::exception 20 | { 21 | public: 22 | //! Defined RtError types. 23 | enum Type { 24 | WARNING, /*!< A non-critical error. */ 25 | DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ 26 | UNSPECIFIED, /*!< The default, unspecified error type. */ 27 | NO_DEVICES_FOUND, /*!< No devices found on system. */ 28 | INVALID_DEVICE, /*!< An invalid device ID was specified. */ 29 | MEMORY_ERROR, /*!< An error occured during memory allocation. */ 30 | INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ 31 | INVALID_USE, /*!< The function was called incorrectly. */ 32 | DRIVER_ERROR, /*!< A system driver error occured. */ 33 | SYSTEM_ERROR, /*!< A system error occured. */ 34 | THREAD_ERROR /*!< A thread error occured. */ 35 | }; 36 | 37 | //! The constructor. 38 | RtError( const std::string& message, Type type = RtError::UNSPECIFIED ) throw() : message_(message), type_(type) {} 39 | 40 | //! The destructor. 41 | virtual ~RtError( void ) throw() {} 42 | 43 | //! Prints thrown error message to stderr. 44 | virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } 45 | 46 | //! Returns the thrown error message type. 47 | virtual const Type& getType(void) const throw() { return type_; } 48 | 49 | //! Returns the thrown error message string. 50 | virtual const std::string& getMessage(void) const throw() { return message_; } 51 | 52 | //! Returns the thrown error message as a c-style string. 53 | virtual const char* what( void ) const throw() { return message_.c_str(); } 54 | 55 | protected: 56 | std::string message_; 57 | Type type_; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /rtmidi/msw/readme: -------------------------------------------------------------------------------- 1 | This directory contains a Visual Studio 2008 project, contributed by Jason Champion, to build rtmidi as a library. The library builds to the \lib directory. -------------------------------------------------------------------------------- /rtmidi/msw/rtmidilib.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rtmidilib", "rtmidilib.vcproj", "{EBFE5EB3-182A-47A6-922B-52ECF777F6A3}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Debug|Win32.Build.0 = Debug|Win32 14 | {EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Release|Win32.ActiveCfg = Release|Win32 15 | {EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /rtmidi/msw/rtmidilib.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 25 | 28 | 31 | 34 | 37 | 40 | 50 | 53 | 56 | 59 | 63 | 66 | 69 | 72 | 75 | 78 | 79 | 87 | 90 | 93 | 96 | 99 | 102 | 112 | 115 | 118 | 121 | 125 | 128 | 131 | 134 | 137 | 140 | 141 | 142 | 143 | 144 | 145 | 150 | 153 | 154 | 155 | 160 | 163 | 164 | 167 | 168 | 169 | 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /rtmidi/readme: -------------------------------------------------------------------------------- 1 | RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output across GNU/Linux (ALSA & Jack), Macintosh OS X (CoreMidi) and Windows (Multimedia & Kernel Streaming). 2 | 3 | By Gary P. Scavone, 2003-2012. 4 | 5 | This distribution of RtMidi contains the following: 6 | 7 | doc: RtMidi documentation (see doc/html/index.html) 8 | tests: example RtMidi programs 9 | 10 | On unix systems, type "./configure" in the top level directory, then "make" in the tests/ directory to compile the test programs. In Windows, open the Visual C++ workspace file located in the tests/ directory. 11 | 12 | OVERVIEW: 13 | 14 | RtMidi is a set of C++ classes (RtMidiIn, RtMidiOut, and API specific classes) that provide a common API (Application Programming Interface) for realtime MIDI input/output across GNU/Linux (ALSA, Jack), Macintosh OS X (CoreMidi, Jack), SGI, and Windows (Multimedia Library, Kernel Streming) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: 15 | 16 | - object oriented C++ design 17 | - simple, common API across all supported platforms 18 | - only two header files and one source file for easy inclusion in programming projects 19 | - MIDI device enumeration 20 | 21 | MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a double floating point type). MIDI data is passed to the user as raw bytes using an std::vector. 22 | 23 | FURTHER READING: 24 | 25 | For complete documentation on RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/. 26 | 27 | 28 | LEGAL AND ETHICAL: 29 | 30 | The RtMidi license is similar to the the MIT License, with the added "feature" that modifications be sent to the developer. 31 | 32 | RtMidi: realtime MIDI i/o C++ classes 33 | Copyright (c) 2003-2012 Gary P. Scavone 34 | 35 | Permission is hereby granted, free of charge, to any person 36 | obtaining a copy of this software and associated documentation files 37 | (the "Software"), to deal in the Software without restriction, 38 | including without limitation the rights to use, copy, modify, merge, 39 | publish, distribute, sublicense, and/or sell copies of the Software, 40 | and to permit persons to whom the Software is furnished to do so, 41 | subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be 44 | included in all copies or substantial portions of the Software. 45 | 46 | Any person wishing to distribute modifications to the Software is 47 | asked to send the modifications to the original developer so that 48 | they can be incorporated into the canonical version. This is, 49 | however, not a binding provision of this license. 50 | 51 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 52 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 53 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 54 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 55 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 56 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 57 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | -------------------------------------------------------------------------------- /rtmidi/rtmidi-config.in: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | if (test "x$#" != "x1") ; then 3 | echo "Usage: $0 [--libs | --cxxflags | --cppflags]" 4 | exit; 5 | fi 6 | 7 | LIBRARY="@LIBS@" 8 | CXXFLAGS="@CXXFLAGS@" 9 | CPPFLAGS="@CPPFLAGS@" 10 | 11 | if (test "x$1" == "x--libs") ; then 12 | echo "$LIBRARY" 13 | elif (test "x$1" == "x--cxxflags") ; then 14 | echo "$CXXFLAGS" 15 | elif (test "x$1" == "x--cppflags") ; then 16 | echo "$CPPFLAGS" 17 | else 18 | echo "Unknown option: $1" 19 | fi 20 | -------------------------------------------------------------------------------- /rtmidi/tests/Makefile.in: -------------------------------------------------------------------------------- 1 | ### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in 2 | ### RtMidi tests Makefile - for various flavors of unix 3 | 4 | PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest 5 | RM = /bin/rm 6 | SRC_PATH = .. 7 | INCLUDE = .. 8 | OBJECT_PATH = @object_path@ 9 | vpath %.o $(OBJECT_PATH) 10 | 11 | OBJECTS = RtMidi.o 12 | 13 | CC = @CXX@ 14 | DEFS = @CPPFLAGS@ 15 | CFLAGS = @CXXFLAGS@ 16 | CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/include 17 | LIBRARY = @LIBS@ 18 | 19 | %.o : $(SRC_PATH)/%.cpp 20 | $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@ 21 | 22 | all : $(PROGRAMS) 23 | 24 | midiprobe : midiprobe.cpp $(OBJECTS) 25 | $(CC) $(CFLAGS) $(DEFS) -o midiprobe midiprobe.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) 26 | 27 | midiout : midiout.cpp $(OBJECTS) 28 | $(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) 29 | 30 | qmidiin : qmidiin.cpp $(OBJECTS) 31 | $(CC) $(CFLAGS) $(DEFS) -o qmidiin qmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) 32 | 33 | cmidiin : cmidiin.cpp $(OBJECTS) 34 | $(CC) $(CFLAGS) $(DEFS) -o cmidiin cmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) 35 | 36 | sysextest : sysextest.cpp $(OBJECTS) 37 | $(CC) $(CFLAGS) $(DEFS) -o sysextest sysextest.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) 38 | 39 | clean : 40 | $(RM) -f $(OBJECT_PATH)/*.o 41 | $(RM) -f $(PROGRAMS) *.exe 42 | $(RM) -f *~ 43 | 44 | distclean: clean 45 | $(RM) -f Makefile 46 | 47 | strip : 48 | strip $(PROGRAMS) 49 | -------------------------------------------------------------------------------- /rtmidi/tests/RtMidi.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | 4 | ############################################################################### 5 | 6 | Project: "cmidiin"=".\cmidiin.dsp" - Package Owner=<4> 7 | 8 | Package=<5> 9 | {{{ 10 | }}} 11 | 12 | Package=<4> 13 | {{{ 14 | }}} 15 | 16 | ############################################################################### 17 | 18 | Project: "midiout"=".\midiout.dsp" - Package Owner=<4> 19 | 20 | Package=<5> 21 | {{{ 22 | }}} 23 | 24 | Package=<4> 25 | {{{ 26 | }}} 27 | 28 | ############################################################################### 29 | 30 | Project: "midiprobe"=".\midiprobe.dsp" - Package Owner=<4> 31 | 32 | Package=<5> 33 | {{{ 34 | }}} 35 | 36 | Package=<4> 37 | {{{ 38 | }}} 39 | 40 | ############################################################################### 41 | 42 | Project: "qmidiin"=".\qmidiin.dsp" - Package Owner=<4> 43 | 44 | Package=<5> 45 | {{{ 46 | }}} 47 | 48 | Package=<4> 49 | {{{ 50 | }}} 51 | 52 | ############################################################################### 53 | 54 | Project: "sysextest"=".\sysextest.dsp" - Package Owner=<4> 55 | 56 | Package=<5> 57 | {{{ 58 | }}} 59 | 60 | Package=<4> 61 | {{{ 62 | }}} 63 | 64 | ############################################################################### 65 | 66 | Global: 67 | 68 | Package=<5> 69 | {{{ 70 | }}} 71 | 72 | Package=<3> 73 | {{{ 74 | }}} 75 | 76 | ############################################################################### 77 | 78 | -------------------------------------------------------------------------------- /rtmidi/tests/cmidiin.cpp: -------------------------------------------------------------------------------- 1 | //*****************************************// 2 | // cmidiin.cpp 3 | // by Gary Scavone, 2003-2004. 4 | // 5 | // Simple program to test MIDI input and 6 | // use of a user callback function. 7 | // 8 | //*****************************************// 9 | 10 | #include 11 | #include 12 | #include "RtMidi.h" 13 | 14 | void usage( void ) { 15 | // Error function in case of incorrect command-line 16 | // argument specifications. 17 | std::cout << "\nuseage: cmidiin \n"; 18 | std::cout << " where port = the device to use (default = 0).\n\n"; 19 | exit( 0 ); 20 | } 21 | 22 | void mycallback( double deltatime, std::vector< unsigned char > *message, void *userData ) 23 | { 24 | unsigned int nBytes = message->size(); 25 | for ( unsigned int i=0; i 0 ) 28 | std::cout << "stamp = " << deltatime << std::endl; 29 | } 30 | 31 | // This function should be embedded in a try/catch block in case of 32 | // an exception. It offers the user a choice of MIDI ports to open. 33 | // It returns false if there are no ports available. 34 | bool chooseMidiPort( RtMidiIn *rtmidi ); 35 | 36 | int main( int argc, char *argv[] ) 37 | { 38 | RtMidiIn *midiin = 0; 39 | 40 | // Minimal command-line check. 41 | if ( argc > 2 ) usage(); 42 | 43 | try { 44 | 45 | // RtMidiIn constructor 46 | midiin = new RtMidiIn(); 47 | 48 | // Call function to select port. 49 | if ( chooseMidiPort( midiin ) == false ) goto cleanup; 50 | 51 | // Set our callback function. This should be done immediately after 52 | // opening the port to avoid having incoming messages written to the 53 | // queue instead of sent to the callback function. 54 | midiin->setCallback( &mycallback ); 55 | 56 | // Don't ignore sysex, timing, or active sensing messages. 57 | midiin->ignoreTypes( false, false, false ); 58 | 59 | std::cout << "\nReading MIDI input ... press to quit.\n"; 60 | char input; 61 | std::cin.get(input); 62 | 63 | } catch ( RtError &error ) { 64 | error.printMessage(); 65 | } 66 | 67 | cleanup: 68 | 69 | delete midiin; 70 | 71 | return 0; 72 | } 73 | 74 | bool chooseMidiPort( RtMidiIn *rtmidi ) 75 | { 76 | std::cout << "\nWould you like to open a virtual input port? [y/N] "; 77 | 78 | std::string keyHit; 79 | std::getline( std::cin, keyHit ); 80 | if ( keyHit == "y" ) { 81 | rtmidi->openVirtualPort(); 82 | return true; 83 | } 84 | 85 | std::string portName; 86 | unsigned int i = 0, nPorts = rtmidi->getPortCount(); 87 | if ( nPorts == 0 ) { 88 | std::cout << "No input ports available!" << std::endl; 89 | return false; 90 | } 91 | 92 | if ( nPorts == 1 ) { 93 | std::cout << "\nOpening " << rtmidi->getPortName() << std::endl; 94 | } 95 | else { 96 | for ( i=0; igetPortName(i); 98 | std::cout << " Input port #" << i << ": " << portName << '\n'; 99 | } 100 | 101 | do { 102 | std::cout << "\nChoose a port number: "; 103 | std::cin >> i; 104 | } while ( i >= nPorts ); 105 | } 106 | 107 | std::getline( std::cin, keyHit ); // used to clear out stdin 108 | rtmidi->openPort( i ); 109 | 110 | return true; 111 | } 112 | -------------------------------------------------------------------------------- /rtmidi/tests/cmidiin.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="cmidiin" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 6 | 7 | CFG=cmidiin - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "cmidiin.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "cmidiin.mak" CFG="cmidiin - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "cmidiin - Win32 Release" (based on "Win32 (x86) Console Application") 21 | !MESSAGE "cmidiin - Win32 Debug" (based on "Win32 (x86) Console Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | RSC=rc.exe 30 | 31 | !IF "$(CFG)" == "cmidiin - Win32 Release" 32 | 33 | # PROP BASE Use_MFC 0 34 | # PROP BASE Use_Debug_Libraries 0 35 | # PROP BASE Output_Dir "cmidiin___Win32_Release" 36 | # PROP BASE Intermediate_Dir "cmidiin___Win32_Release" 37 | # PROP BASE Target_Dir "" 38 | # PROP Use_MFC 0 39 | # PROP Use_Debug_Libraries 0 40 | # PROP Output_Dir "" 41 | # PROP Intermediate_Dir "Release" 42 | # PROP Ignore_Export_Lib 0 43 | # PROP Target_Dir "" 44 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 | # ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c 46 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 | # ADD RSC /l 0x409 /d "NDEBUG" 48 | BSC32=bscmake.exe 49 | # ADD BASE BSC32 /nologo 50 | # ADD BSC32 /nologo 51 | LINK32=link.exe 52 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 53 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386 54 | 55 | !ELSEIF "$(CFG)" == "cmidiin - Win32 Debug" 56 | 57 | # PROP BASE Use_MFC 0 58 | # PROP BASE Use_Debug_Libraries 1 59 | # PROP BASE Output_Dir "cmidiin___Win32_Debug" 60 | # PROP BASE Intermediate_Dir "cmidiin___Win32_Debug" 61 | # PROP BASE Target_Dir "" 62 | # PROP Use_MFC 0 63 | # PROP Use_Debug_Libraries 1 64 | # PROP Output_Dir "" 65 | # PROP Intermediate_Dir "Debug" 66 | # PROP Ignore_Export_Lib 0 67 | # PROP Target_Dir "" 68 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c 70 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 | # ADD RSC /l 0x409 /d "_DEBUG" 72 | BSC32=bscmake.exe 73 | # ADD BASE BSC32 /nologo 74 | # ADD BSC32 /nologo 75 | LINK32=link.exe 76 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 77 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 78 | 79 | !ENDIF 80 | 81 | # Begin Target 82 | 83 | # Name "cmidiin - Win32 Release" 84 | # Name "cmidiin - Win32 Debug" 85 | # Begin Group "Source Files" 86 | 87 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 88 | # Begin Source File 89 | 90 | SOURCE=.\cmidiin.cpp 91 | # End Source File 92 | # Begin Source File 93 | 94 | SOURCE=..\RtMidi.cpp 95 | # End Source File 96 | # End Group 97 | # Begin Group "Header Files" 98 | 99 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 100 | # Begin Source File 101 | 102 | SOURCE=..\RtError.h 103 | # End Source File 104 | # Begin Source File 105 | 106 | SOURCE=..\RtMidi.h 107 | # End Source File 108 | # End Group 109 | # Begin Group "Resource Files" 110 | 111 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 112 | # End Group 113 | # End Target 114 | # End Project 115 | -------------------------------------------------------------------------------- /rtmidi/tests/midiout.cpp: -------------------------------------------------------------------------------- 1 | //*****************************************// 2 | // midiout.cpp 3 | // by Gary Scavone, 2003-2004. 4 | // 5 | // Simple program to test MIDI output. 6 | // 7 | //*****************************************// 8 | 9 | #include 10 | #include 11 | #include "RtMidi.h" 12 | 13 | // Platform-dependent sleep routines. 14 | #if defined(__WINDOWS_MM__) 15 | #include 16 | #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 17 | #else // Unix variants 18 | #include 19 | #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) 20 | #endif 21 | 22 | // This function should be embedded in a try/catch block in case of 23 | // an exception. It offers the user a choice of MIDI ports to open. 24 | // It returns false if there are no ports available. 25 | bool chooseMidiPort( RtMidiOut *rtmidi ); 26 | 27 | int main( int argc, char *argv[] ) 28 | { 29 | RtMidiOut *midiout = 0; 30 | std::vector message; 31 | 32 | // RtMidiOut constructor 33 | try { 34 | midiout = new RtMidiOut(); 35 | } 36 | catch ( RtError &error ) { 37 | error.printMessage(); 38 | exit( EXIT_FAILURE ); 39 | } 40 | 41 | // Call function to select port. 42 | try { 43 | if ( chooseMidiPort( midiout ) == false ) goto cleanup; 44 | } 45 | catch ( RtError &error ) { 46 | error.printMessage(); 47 | goto cleanup; 48 | } 49 | 50 | // Send out a series of MIDI messages. 51 | 52 | // Program change: 192, 5 53 | message.push_back( 192 ); 54 | message.push_back( 5 ); 55 | midiout->sendMessage( &message ); 56 | 57 | SLEEP( 500 ); 58 | 59 | message[0] = 0xF1; 60 | message[1] = 60; 61 | midiout->sendMessage( &message ); 62 | 63 | // Control Change: 176, 7, 100 (volume) 64 | message[0] = 176; 65 | message[1] = 7; 66 | message.push_back( 100 ); 67 | midiout->sendMessage( &message ); 68 | 69 | // Note On: 144, 64, 90 70 | message[0] = 144; 71 | message[1] = 64; 72 | message[2] = 90; 73 | midiout->sendMessage( &message ); 74 | 75 | SLEEP( 500 ); 76 | 77 | // Note Off: 128, 64, 40 78 | message[0] = 128; 79 | message[1] = 64; 80 | message[2] = 40; 81 | midiout->sendMessage( &message ); 82 | 83 | SLEEP( 500 ); 84 | 85 | // Control Change: 176, 7, 40 86 | message[0] = 176; 87 | message[1] = 7; 88 | message[2] = 40; 89 | midiout->sendMessage( &message ); 90 | 91 | SLEEP( 500 ); 92 | 93 | // Sysex: 240, 67, 4, 3, 2, 247 94 | message[0] = 240; 95 | message[1] = 67; 96 | message[2] = 4; 97 | message.push_back( 3 ); 98 | message.push_back( 2 ); 99 | message.push_back( 247 ); 100 | midiout->sendMessage( &message ); 101 | 102 | // Clean up 103 | cleanup: 104 | delete midiout; 105 | 106 | return 0; 107 | } 108 | 109 | bool chooseMidiPort( RtMidiOut *rtmidi ) 110 | { 111 | std::cout << "\nWould you like to open a virtual output port? [y/N] "; 112 | 113 | std::string keyHit; 114 | std::getline( std::cin, keyHit ); 115 | if ( keyHit == "y" ) { 116 | rtmidi->openVirtualPort(); 117 | return true; 118 | } 119 | 120 | std::string portName; 121 | unsigned int i = 0, nPorts = rtmidi->getPortCount(); 122 | if ( nPorts == 0 ) { 123 | std::cout << "No output ports available!" << std::endl; 124 | return false; 125 | } 126 | 127 | if ( nPorts == 1 ) { 128 | std::cout << "\nOpening " << rtmidi->getPortName() << std::endl; 129 | } 130 | else { 131 | for ( i=0; igetPortName(i); 133 | std::cout << " Output port #" << i << ": " << portName << '\n'; 134 | } 135 | 136 | do { 137 | std::cout << "\nChoose a port number: "; 138 | std::cin >> i; 139 | } while ( i >= nPorts ); 140 | } 141 | 142 | std::cout << "\n"; 143 | rtmidi->openPort( i ); 144 | 145 | return true; 146 | } 147 | -------------------------------------------------------------------------------- /rtmidi/tests/midiout.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="midiout" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 6 | 7 | CFG=midiout - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "midiout.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "midiout.mak" CFG="midiout - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "midiout - Win32 Release" (based on "Win32 (x86) Console Application") 21 | !MESSAGE "midiout - Win32 Debug" (based on "Win32 (x86) Console Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | RSC=rc.exe 30 | 31 | !IF "$(CFG)" == "midiout - Win32 Release" 32 | 33 | # PROP BASE Use_MFC 0 34 | # PROP BASE Use_Debug_Libraries 0 35 | # PROP BASE Output_Dir "midiout___Win32_Release" 36 | # PROP BASE Intermediate_Dir "midiout___Win32_Release" 37 | # PROP BASE Target_Dir "" 38 | # PROP Use_MFC 0 39 | # PROP Use_Debug_Libraries 0 40 | # PROP Output_Dir "" 41 | # PROP Intermediate_Dir "Release" 42 | # PROP Ignore_Export_Lib 0 43 | # PROP Target_Dir "" 44 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 | # ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c 46 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 | # ADD RSC /l 0x409 /d "NDEBUG" 48 | BSC32=bscmake.exe 49 | # ADD BASE BSC32 /nologo 50 | # ADD BSC32 /nologo 51 | LINK32=link.exe 52 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 53 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386 54 | 55 | !ELSEIF "$(CFG)" == "midiout - Win32 Debug" 56 | 57 | # PROP BASE Use_MFC 0 58 | # PROP BASE Use_Debug_Libraries 1 59 | # PROP BASE Output_Dir "midiout___Win32_Debug" 60 | # PROP BASE Intermediate_Dir "midiout___Win32_Debug" 61 | # PROP BASE Target_Dir "" 62 | # PROP Use_MFC 0 63 | # PROP Use_Debug_Libraries 1 64 | # PROP Output_Dir "" 65 | # PROP Intermediate_Dir "Debug" 66 | # PROP Ignore_Export_Lib 0 67 | # PROP Target_Dir "" 68 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c 70 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 | # ADD RSC /l 0x409 /d "_DEBUG" 72 | BSC32=bscmake.exe 73 | # ADD BASE BSC32 /nologo 74 | # ADD BSC32 /nologo 75 | LINK32=link.exe 76 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 77 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 78 | 79 | !ENDIF 80 | 81 | # Begin Target 82 | 83 | # Name "midiout - Win32 Release" 84 | # Name "midiout - Win32 Debug" 85 | # Begin Group "Source Files" 86 | 87 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 88 | # Begin Source File 89 | 90 | SOURCE=.\midiout.cpp 91 | # End Source File 92 | # Begin Source File 93 | 94 | SOURCE=..\RtMidi.cpp 95 | # End Source File 96 | # End Group 97 | # Begin Group "Header Files" 98 | 99 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 100 | # Begin Source File 101 | 102 | SOURCE=..\RtError.h 103 | # End Source File 104 | # Begin Source File 105 | 106 | SOURCE=..\RtMidi.h 107 | # End Source File 108 | # End Group 109 | # Begin Group "Resource Files" 110 | 111 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 112 | # End Group 113 | # End Target 114 | # End Project 115 | -------------------------------------------------------------------------------- /rtmidi/tests/midiprobe.cpp: -------------------------------------------------------------------------------- 1 | // midiprobe.cpp 2 | // 3 | // Simple program to check MIDI inputs and outputs. 4 | // 5 | // by Gary Scavone, 2003-2012. 6 | 7 | #include 8 | #include 9 | #include 10 | #include "RtMidi.h" 11 | 12 | int main() 13 | { 14 | // Create an api map. 15 | std::map apiMap; 16 | apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMidi"; 17 | apiMap[RtMidi::WINDOWS_MM] = "Windows MultiMedia"; 18 | apiMap[RtMidi::WINDOWS_KS] = "Windows Kernel Straming"; 19 | apiMap[RtMidi::UNIX_JACK] = "Jack Client"; 20 | apiMap[RtMidi::LINUX_ALSA] = "Linux ALSA"; 21 | apiMap[RtMidi::RTMIDI_DUMMY] = "RtMidi Dummy"; 22 | 23 | std::vector< RtMidi::Api > apis; 24 | RtMidi :: getCompiledApi( apis ); 25 | 26 | std::cout << "\nCompiled APIs:\n"; 27 | for ( unsigned int i=0; igetCurrentApi() ] << std::endl; 39 | 40 | // Check inputs. 41 | unsigned int nPorts = midiin->getPortCount(); 42 | std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n"; 43 | 44 | for ( unsigned i=0; igetPortName(i); 46 | std::cout << " Input Port #" << i+1 << ": " << portName << '\n'; 47 | } 48 | 49 | // RtMidiOut constructor ... exception possible 50 | midiout = new RtMidiOut(); 51 | 52 | std::cout << "\nCurrent output API: " << apiMap[ midiout->getCurrentApi() ] << std::endl; 53 | 54 | // Check outputs. 55 | nPorts = midiout->getPortCount(); 56 | std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n"; 57 | 58 | for ( unsigned i=0; igetPortName(i); 60 | std::cout << " Output Port #" << i+1 << ": " << portName << std::endl; 61 | } 62 | std::cout << std::endl; 63 | 64 | } catch ( RtError &error ) { 65 | error.printMessage(); 66 | } 67 | 68 | delete midiin; 69 | delete midiout; 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /rtmidi/tests/midiprobe.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="midiprobe" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 6 | 7 | CFG=midiprobe - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "midiprobe.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "midiprobe.mak" CFG="midiprobe - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "midiprobe - Win32 Release" (based on "Win32 (x86) Console Application") 21 | !MESSAGE "midiprobe - Win32 Debug" (based on "Win32 (x86) Console Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | RSC=rc.exe 30 | 31 | !IF "$(CFG)" == "midiprobe - Win32 Release" 32 | 33 | # PROP BASE Use_MFC 0 34 | # PROP BASE Use_Debug_Libraries 0 35 | # PROP BASE Output_Dir "midiprobe___Win32_Release" 36 | # PROP BASE Intermediate_Dir "midiprobe___Win32_Release" 37 | # PROP BASE Target_Dir "" 38 | # PROP Use_MFC 0 39 | # PROP Use_Debug_Libraries 0 40 | # PROP Output_Dir "" 41 | # PROP Intermediate_Dir "Release" 42 | # PROP Ignore_Export_Lib 0 43 | # PROP Target_Dir "" 44 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 | # ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c 46 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 | # ADD RSC /l 0x409 /d "NDEBUG" 48 | BSC32=bscmake.exe 49 | # ADD BASE BSC32 /nologo 50 | # ADD BSC32 /nologo 51 | LINK32=link.exe 52 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 53 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386 54 | 55 | !ELSEIF "$(CFG)" == "midiprobe - Win32 Debug" 56 | 57 | # PROP BASE Use_MFC 0 58 | # PROP BASE Use_Debug_Libraries 1 59 | # PROP BASE Output_Dir "midiprobe___Win32_Debug" 60 | # PROP BASE Intermediate_Dir "midiprobe___Win32_Debug" 61 | # PROP BASE Target_Dir "" 62 | # PROP Use_MFC 0 63 | # PROP Use_Debug_Libraries 1 64 | # PROP Output_Dir "" 65 | # PROP Intermediate_Dir "Debug" 66 | # PROP Ignore_Export_Lib 0 67 | # PROP Target_Dir "" 68 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c 70 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 | # ADD RSC /l 0x409 /d "_DEBUG" 72 | BSC32=bscmake.exe 73 | # ADD BASE BSC32 /nologo 74 | # ADD BSC32 /nologo 75 | LINK32=link.exe 76 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 77 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 78 | 79 | !ENDIF 80 | 81 | # Begin Target 82 | 83 | # Name "midiprobe - Win32 Release" 84 | # Name "midiprobe - Win32 Debug" 85 | # Begin Group "Source Files" 86 | 87 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 88 | # Begin Source File 89 | 90 | SOURCE=.\midiprobe.cpp 91 | # End Source File 92 | # Begin Source File 93 | 94 | SOURCE=..\RtMidi.cpp 95 | # End Source File 96 | # End Group 97 | # Begin Group "Header Files" 98 | 99 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 100 | # Begin Source File 101 | 102 | SOURCE=..\RtError.h 103 | # End Source File 104 | # Begin Source File 105 | 106 | SOURCE=..\RtMidi.h 107 | # End Source File 108 | # End Group 109 | # Begin Group "Resource Files" 110 | 111 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 112 | # End Group 113 | # End Target 114 | # End Project 115 | -------------------------------------------------------------------------------- /rtmidi/tests/qmidiin.cpp: -------------------------------------------------------------------------------- 1 | //*****************************************// 2 | // qmidiin.cpp 3 | // by Gary Scavone, 2003-2004. 4 | // 5 | // Simple program to test MIDI input and 6 | // retrieval from the queue. 7 | // 8 | //*****************************************// 9 | 10 | #include 11 | #include 12 | #include 13 | #include "RtMidi.h" 14 | 15 | // Platform-dependent sleep routines. 16 | #if defined(__WINDOWS_MM__) 17 | #include 18 | #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 19 | #else // Unix variants 20 | #include 21 | #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) 22 | #endif 23 | 24 | bool done; 25 | static void finish( int ignore ){ done = true; } 26 | 27 | void usage( void ) { 28 | // Error function in case of incorrect command-line 29 | // argument specifications. 30 | std::cout << "\nusage: qmidiin \n"; 31 | std::cout << " where port = the device to use (default = 0).\n\n"; 32 | exit( 0 ); 33 | } 34 | 35 | int main( int argc, char *argv[] ) 36 | { 37 | RtMidiIn *midiin = 0; 38 | std::vector message; 39 | int nBytes, i; 40 | double stamp; 41 | 42 | // Minimal command-line check. 43 | if ( argc > 2 ) usage(); 44 | 45 | // RtMidiIn constructor 46 | try { 47 | midiin = new RtMidiIn(); 48 | } 49 | catch ( RtError &error ) { 50 | error.printMessage(); 51 | exit( EXIT_FAILURE ); 52 | } 53 | 54 | // Check available ports vs. specified. 55 | unsigned int port = 0; 56 | unsigned int nPorts = midiin->getPortCount(); 57 | if ( argc == 2 ) port = (unsigned int) atoi( argv[1] ); 58 | if ( port >= nPorts ) { 59 | delete midiin; 60 | std::cout << "Invalid port specifier!\n"; 61 | usage(); 62 | } 63 | 64 | try { 65 | midiin->openPort( port ); 66 | } 67 | catch ( RtError &error ) { 68 | error.printMessage(); 69 | goto cleanup; 70 | } 71 | 72 | // Don't ignore sysex, timing, or active sensing messages. 73 | midiin->ignoreTypes( false, false, false ); 74 | 75 | // Install an interrupt handler function. 76 | done = false; 77 | (void) signal(SIGINT, finish); 78 | 79 | // Periodically check input queue. 80 | std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; 81 | while ( !done ) { 82 | stamp = midiin->getMessage( &message ); 83 | nBytes = message.size(); 84 | for ( i=0; i 0 ) 87 | std::cout << "stamp = " << stamp << std::endl; 88 | 89 | // Sleep for 10 milliseconds. 90 | SLEEP( 10 ); 91 | } 92 | 93 | // Clean up 94 | cleanup: 95 | delete midiin; 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /rtmidi/tests/qmidiin.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="qmidiin" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 6 | 7 | CFG=qmidiin - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "qmidiin.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "qmidiin.mak" CFG="qmidiin - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "qmidiin - Win32 Release" (based on "Win32 (x86) Console Application") 21 | !MESSAGE "qmidiin - Win32 Debug" (based on "Win32 (x86) Console Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | RSC=rc.exe 30 | 31 | !IF "$(CFG)" == "qmidiin - Win32 Release" 32 | 33 | # PROP BASE Use_MFC 0 34 | # PROP BASE Use_Debug_Libraries 0 35 | # PROP BASE Output_Dir "qmidiin___Win32_Release" 36 | # PROP BASE Intermediate_Dir "qmidiin___Win32_Release" 37 | # PROP BASE Target_Dir "" 38 | # PROP Use_MFC 0 39 | # PROP Use_Debug_Libraries 0 40 | # PROP Output_Dir "" 41 | # PROP Intermediate_Dir "Release" 42 | # PROP Ignore_Export_Lib 0 43 | # PROP Target_Dir "" 44 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 | # ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c 46 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 | # ADD RSC /l 0x409 /d "NDEBUG" 48 | BSC32=bscmake.exe 49 | # ADD BASE BSC32 /nologo 50 | # ADD BSC32 /nologo 51 | LINK32=link.exe 52 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 53 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386 54 | 55 | !ELSEIF "$(CFG)" == "qmidiin - Win32 Debug" 56 | 57 | # PROP BASE Use_MFC 0 58 | # PROP BASE Use_Debug_Libraries 1 59 | # PROP BASE Output_Dir "qmidiin___Win32_Debug" 60 | # PROP BASE Intermediate_Dir "qmidiin___Win32_Debug" 61 | # PROP BASE Target_Dir "" 62 | # PROP Use_MFC 0 63 | # PROP Use_Debug_Libraries 1 64 | # PROP Output_Dir "" 65 | # PROP Intermediate_Dir "Debug" 66 | # PROP Ignore_Export_Lib 0 67 | # PROP Target_Dir "" 68 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c 70 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 | # ADD RSC /l 0x409 /d "_DEBUG" 72 | BSC32=bscmake.exe 73 | # ADD BASE BSC32 /nologo 74 | # ADD BSC32 /nologo 75 | LINK32=link.exe 76 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 77 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept 78 | 79 | !ENDIF 80 | 81 | # Begin Target 82 | 83 | # Name "qmidiin - Win32 Release" 84 | # Name "qmidiin - Win32 Debug" 85 | # Begin Group "Source Files" 86 | 87 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 88 | # Begin Source File 89 | 90 | SOURCE=.\qmidiin.cpp 91 | # End Source File 92 | # Begin Source File 93 | 94 | SOURCE=..\RtMidi.cpp 95 | # End Source File 96 | # End Group 97 | # Begin Group "Header Files" 98 | 99 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 100 | # Begin Source File 101 | 102 | SOURCE=..\RtError.h 103 | # End Source File 104 | # Begin Source File 105 | 106 | SOURCE=..\RtMidi.h 107 | # End Source File 108 | # End Group 109 | # Begin Group "Resource Files" 110 | 111 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 112 | # End Group 113 | # End Target 114 | # End Project 115 | -------------------------------------------------------------------------------- /rtmidi/tests/sysextest.cpp: -------------------------------------------------------------------------------- 1 | //*****************************************// 2 | // sysextest.cpp 3 | // by Gary Scavone, 2003-2005. 4 | // 5 | // Simple program to test MIDI sysex sending and receiving. 6 | // 7 | //*****************************************// 8 | 9 | #include 10 | #include 11 | #include 12 | #include "RtMidi.h" 13 | 14 | void usage( void ) { 15 | std::cout << "\nuseage: sysextest N\n"; 16 | std::cout << " where N = length of sysex message to send / receive.\n\n"; 17 | exit( 0 ); 18 | } 19 | 20 | // Platform-dependent sleep routines. 21 | #if defined(__WINDOWS_MM__) 22 | #include 23 | #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 24 | #else // Unix variants 25 | #include 26 | #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) 27 | #endif 28 | 29 | // This function should be embedded in a try/catch block in case of 30 | // an exception. It offers the user a choice of MIDI ports to open. 31 | // It returns false if there are no ports available. 32 | bool chooseMidiPort( RtMidi *rtmidi ); 33 | 34 | void mycallback( double deltatime, std::vector< unsigned char > *message, void *userData ) 35 | { 36 | unsigned int nBytes = message->size(); 37 | for ( unsigned int i=0; i 0 ) 40 | std::cout << "stamp = " << deltatime << std::endl; 41 | } 42 | 43 | int main( int argc, char *argv[] ) 44 | { 45 | RtMidiOut *midiout = 0; 46 | RtMidiIn *midiin = 0; 47 | std::vector message; 48 | unsigned int i, nBytes; 49 | 50 | // Minimal command-line check. 51 | if ( argc != 2 ) usage(); 52 | nBytes = (unsigned int) atoi( argv[1] ); 53 | 54 | // RtMidiOut and RtMidiIn constructors 55 | try { 56 | midiout = new RtMidiOut(); 57 | midiin = new RtMidiIn(); 58 | } 59 | catch ( RtError &error ) { 60 | error.printMessage(); 61 | goto cleanup; 62 | } 63 | 64 | // Don't ignore sysex, timing, or active sensing messages. 65 | midiin->ignoreTypes( false, true, true ); 66 | 67 | // Call function to select ports 68 | try { 69 | if ( chooseMidiPort( midiin ) == false ) goto cleanup; 70 | if ( chooseMidiPort( midiout ) == false ) goto cleanup; 71 | } 72 | catch ( RtError &error ) { 73 | error.printMessage(); 74 | goto cleanup; 75 | } 76 | 77 | midiin->setCallback( &mycallback ); 78 | 79 | message.push_back( 0xF6 ); 80 | midiout->sendMessage( &message ); 81 | SLEEP( 500 ); // pause a little 82 | 83 | // Create a long sysex messages of numbered bytes and send it out. 84 | for ( int n=0; n<2; n++ ) { 85 | message.clear(); 86 | message.push_back( 240 ); 87 | for ( i=0; isendMessage( &message ); 91 | 92 | SLEEP( 500 ); // pause a little 93 | 94 | } 95 | 96 | // Clean up 97 | cleanup: 98 | delete midiout; 99 | delete midiin; 100 | 101 | return 0; 102 | } 103 | 104 | bool chooseMidiPort( RtMidi *rtmidi ) 105 | { 106 | bool isInput = false; 107 | if ( typeid( *rtmidi ) == typeid( RtMidiIn ) ) 108 | isInput = true; 109 | 110 | if ( isInput ) 111 | std::cout << "\nWould you like to open a virtual input port? [y/N] "; 112 | else 113 | std::cout << "\nWould you like to open a virtual output port? [y/N] "; 114 | 115 | std::string keyHit; 116 | std::getline( std::cin, keyHit ); 117 | if ( keyHit == "y" ) { 118 | rtmidi->openVirtualPort(); 119 | return true; 120 | } 121 | 122 | std::string portName; 123 | unsigned int i = 0, nPorts = rtmidi->getPortCount(); 124 | if ( nPorts == 0 ) { 125 | if ( isInput ) 126 | std::cout << "No input ports available!" << std::endl; 127 | else 128 | std::cout << "No output ports available!" << std::endl; 129 | return false; 130 | } 131 | 132 | if ( nPorts == 1 ) { 133 | std::cout << "\nOpening " << rtmidi->getPortName() << std::endl; 134 | } 135 | else { 136 | for ( i=0; igetPortName(i); 138 | if ( isInput ) 139 | std::cout << " Input port #" << i << ": " << portName << '\n'; 140 | else 141 | std::cout << " Output port #" << i << ": " << portName << '\n'; 142 | } 143 | 144 | do { 145 | std::cout << "\nChoose a port number: "; 146 | std::cin >> i; 147 | } while ( i >= nPorts ); 148 | } 149 | 150 | std::cout << std::endl; 151 | rtmidi->openPort( i ); 152 | 153 | return true; 154 | } 155 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = cursynth 2 | patchesdir = $(pkgdatadir)/patches 3 | 4 | cursynth_SOURCES = main.cpp \ 5 | cursynth.cpp \ 6 | cursynth_engine.cpp \ 7 | cursynth_gui.cpp \ 8 | cursynth_strings.cpp \ 9 | cursynth.h \ 10 | cursynth_common.h \ 11 | cursynth_engine.h \ 12 | cursynth_gui.h \ 13 | cursynth_strings.h 14 | 15 | cursynth_CPPFLAGS = -I. \ 16 | -I.. \ 17 | -I$(top_srcdir)/cJSON \ 18 | -I$(top_srcdir)/rtaudio \ 19 | -I$(top_srcdir)/rtmidi \ 20 | -I$(top_srcdir)/mopo/src \ 21 | -I$(top_srcdir)/mopo/src \ 22 | -I/usr/local/opt/gettext/include \ 23 | -DPATCHES_DIRECTORY=\"$(patchesdir)\" 24 | 25 | cursynth_LDADD = ../cJSON/libcJSON.a \ 26 | ../rtaudio/librtaudio.a \ 27 | ../rtmidi/librtmidi.a \ 28 | ../mopo/src/libmopo.a 29 | -------------------------------------------------------------------------------- /src/cursynth.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * cursynth is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * cursynth is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with cursynth. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef CURSYNTH_H 19 | #define CURSYNTH_H 20 | 21 | #include "RtAudio.h" 22 | #include "RtMidi.h" 23 | #include "cursynth_gui.h" 24 | #include "cursynth_engine.h" 25 | 26 | #include 27 | 28 | namespace mopo { 29 | 30 | class Cursynth { 31 | public: 32 | // Computer keyboard reading states. 33 | enum InputState { 34 | STANDARD, 35 | MIDI_LEARN, 36 | PATCH_LOADING, 37 | PATCH_SAVING, 38 | }; 39 | 40 | Cursynth(); 41 | 42 | // Start/stop everything - UI, synth engine, input/output. 43 | void start(unsigned sample_rate, unsigned buffer_size); 44 | void stop(); 45 | 46 | // Runs the synth engine for _n_frames_ samples and copies the output 47 | // to _out_buffer_. 48 | void processAudio(mopo_float *out_buffer, unsigned int n_frames); 49 | 50 | // Processes MIDI data like note and velocity, and knob data. 51 | void processMidi(std::vector* message); 52 | 53 | // If we're working with the synth or UI, lock so we don't break 54 | // something. Then unlock when we're done. 55 | void lock() { pthread_mutex_lock(&mutex_); } 56 | void unlock() { pthread_mutex_unlock(&mutex_); } 57 | 58 | private: 59 | unsigned int chooseSampleRate(const RtAudio::DeviceInfo& device, 60 | unsigned preferred_sample_rate); 61 | 62 | // Load and save global configuration settings (like MIDI learn). 63 | void loadConfiguration(); 64 | void saveConfiguration(); 65 | 66 | // Writes the synth state to a string so we can save it to a patch. 67 | std::string writeStateToString(); 68 | // Read the synth state from a string. 69 | void readStateFromString(const std::string& state); 70 | 71 | // Saves the state to a given filename. 72 | void saveToFile(const std::string& file_name); 73 | void loadFromFile(const std::string& file_name); 74 | 75 | // When the user enters help state. Show controls and contact. 76 | void startHelp(); 77 | 78 | // When user starts to load, launch patch browser. 79 | void startLoad(); 80 | 81 | // When user starts to save, start save text field. 82 | void startSave(); 83 | 84 | // Computer keyboard text input callback. 85 | bool textInput(int key); 86 | 87 | // Setup functions initialize objects and callbacks. 88 | void setupAudio(unsigned sample_rate, unsigned buffer_size); 89 | void setupMidi(); 90 | void setupControls(); 91 | void setupGui(); 92 | 93 | // Clear screen and redraw GUI 94 | void refreshGui(); 95 | 96 | // Helper function to erase all evidence of MIDI learn for a control. 97 | void eraseMidiLearn(Control* control); 98 | 99 | // Cursynth parts. 100 | CursynthEngine synth_; 101 | CursynthGui gui_; 102 | 103 | // IO. 104 | RtAudio dac_; 105 | std::vector midi_ins_; 106 | std::map midi_learn_; 107 | 108 | // State. 109 | InputState state_; 110 | control_map controls_; 111 | pthread_mutex_t mutex_; 112 | 113 | // Loading and Saving. 114 | std::vector patches_; 115 | int patch_load_index_; 116 | }; 117 | } // namespace mopo 118 | 119 | #endif // CURSYNTH_H 120 | -------------------------------------------------------------------------------- /src/cursynth_common.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * cursynth is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * cursynth is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with cursynth. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef CURSYNTH_COMMON_H 19 | #define CURSYNTH_COMMON_H 20 | 21 | #include "config.h" 22 | #include "value.h" 23 | 24 | #include 25 | #include 26 | 27 | namespace mopo { 28 | 29 | // A container for a given control its metadata such as maximum and minimum 30 | // value. 31 | class Control { 32 | public: 33 | Control(Value* value, mopo_float min, mopo_float max, int resolution) : 34 | value_(value), min_(min), max_(max), 35 | resolution_(resolution), midi_learn_(0) { 36 | current_value_ = value->value(); 37 | } 38 | 39 | Control(Value* value, std::vector strings, int resolution) : 40 | value_(value), min_(0), max_(resolution), 41 | resolution_(resolution), midi_learn_(0), display_strings_(strings) { 42 | current_value_ = value->value(); 43 | } 44 | 45 | Control() : value_(0), min_(0), max_(0), current_value_(0), 46 | resolution_(0), midi_learn_(0) { } 47 | 48 | void set(mopo_float val) { 49 | current_value_ = CLAMP(val, min_, max_); 50 | value_->set(current_value_); 51 | } 52 | 53 | mopo_float getPercentage() const { 54 | return (current_value_ - min_) / (max_ - min_); 55 | } 56 | 57 | void setPercentage(mopo_float percentage) { 58 | int index = resolution_ * percentage; 59 | set(min_ + index * (max_ - min_) / resolution_); 60 | } 61 | 62 | void setMidi(int midi_val) { 63 | setPercentage(midi_val / (MIDI_SIZE - 1.0)); 64 | } 65 | 66 | void increment() { 67 | set(current_value_ + (max_ - min_) / resolution_); 68 | } 69 | 70 | void decrement() { 71 | set(current_value_ - (max_ - min_) / resolution_); 72 | } 73 | 74 | int midi_learn() const { return midi_learn_; } 75 | 76 | void midi_learn(float midi) { midi_learn_ = midi; } 77 | 78 | std::vector display_strings() const { 79 | return display_strings_; 80 | } 81 | 82 | mopo_float current_value() const { return current_value_; } 83 | 84 | const Value* value() const { return value_; } 85 | 86 | bool isBipolar() const { return max_ == -min_; } 87 | 88 | private: 89 | Value* value_; 90 | mopo_float min_, max_, current_value_; 91 | int resolution_, midi_learn_; 92 | std::vector display_strings_; 93 | }; 94 | 95 | typedef std::map control_map; 96 | typedef std::map input_map; 97 | typedef std::map output_map; 98 | 99 | } // namespace mopo 100 | 101 | #endif // CURSYNTH_COMMON_H 102 | -------------------------------------------------------------------------------- /src/cursynth_gui.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * cursynth is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * cursynth is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with cursynth. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef CURSYNTH_GUI_H 19 | #define CURSYNTH_GUI_H 20 | 21 | #include "mopo.h" 22 | #include "cursynth_common.h" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace mopo { 29 | class Value; 30 | 31 | // Stores information on how and where to draw a control. 32 | struct DisplayDetails { 33 | int x, y, width; 34 | std::string label; 35 | bool bipolar; 36 | }; 37 | 38 | class CursynthGui { 39 | public: 40 | enum ColorIds { 41 | BG_COLOR = 1, 42 | SLIDER_FG_COLOR, 43 | SLIDER_BG_COLOR, 44 | LOGO_COLOR, 45 | SELECTED_COLOR, 46 | PATCH_LOAD_COLOR, 47 | CONTROL_TEXT_COLOR 48 | }; 49 | 50 | CursynthGui() : control_index_(0) { } 51 | 52 | // Start and stop the GUI. 53 | void start(); 54 | void stop(); 55 | void redrawBase(); 56 | 57 | // Add all of the controls for drawing. 58 | void addControls(const control_map& controls); 59 | 60 | void drawHelp(); 61 | void drawMain(); 62 | void drawSlider(const DisplayDetails* slider, 63 | float percentage, bool active); 64 | void drawControl(const Control* control, bool active); 65 | void drawControlStatus(const Control* control, bool armed); 66 | void drawPatchLoading(std::vector patches, int index); 67 | void drawPatchSaving(std::string patch_name); 68 | 69 | void clearPatches(); 70 | 71 | // Linear navigation of controls. 72 | std::string getCurrentControl(); 73 | std::string getNextControl(); 74 | std::string getPrevControl(); 75 | 76 | private: 77 | void drawLogo(); 78 | void drawModulationMatrix(); 79 | void drawMidi(std::string status); 80 | void drawStatus(std::string status); 81 | void drawText(const DisplayDetails* details, 82 | std::string text, bool active); 83 | 84 | // Creates control details and places control in the control order. 85 | DisplayDetails* initControl(std::string name, const Control* control); 86 | 87 | // Place a given control with text display at a location and width. 88 | void placeControl(std::string name, const Control* control, 89 | int x, int y, int width); 90 | 91 | // Place a given control (slider only) at a location and width. 92 | void placeMinimalControl(std::string name, const Control* control, 93 | int x, int y, int width); 94 | 95 | std::map details_lookup_; 96 | std::vector control_order_; 97 | int control_index_; 98 | }; 99 | } // namespace mopo 100 | 101 | #endif // CURSYNTH_GUI_H 102 | -------------------------------------------------------------------------------- /src/cursynth_strings.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * cursynth is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * cursynth is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with cursynth. If not, see . 15 | */ 16 | 17 | #include "cursynth_strings.h" 18 | 19 | namespace mopo { 20 | 21 | const char* CursynthStrings::filter_strings_[] = { 22 | "low pass", 23 | "high pass", 24 | "band pass", 25 | "all pass" 26 | }; 27 | 28 | const char* CursynthStrings::legato_strings_[] = { 29 | "off", 30 | "on" 31 | }; 32 | 33 | const char* CursynthStrings::portamento_strings_[] = { 34 | "off", 35 | "auto", 36 | "on" 37 | }; 38 | 39 | const char* CursynthStrings::wave_strings_[] = { 40 | "sin", 41 | "triangle", 42 | "square", 43 | "down saw", 44 | "up saw", 45 | "three step", 46 | "four step", 47 | "eight step", 48 | "three pyramid", 49 | "five pyramid", 50 | "nine pyramid", 51 | "white noise", 52 | }; 53 | } // namespace mopo 54 | -------------------------------------------------------------------------------- /src/cursynth_strings.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * cursynth is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * cursynth is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with cursynth. If not, see . 15 | */ 16 | 17 | #pragma once 18 | #ifndef CURSYNTH_STRINGS_H 19 | #define CURSYNTH_STRINGS_H 20 | 21 | namespace mopo { 22 | 23 | // Container for all the strings we'll use in the UI. 24 | class CursynthStrings { 25 | public: 26 | static const char* filter_strings_[]; 27 | static const char* legato_strings_[]; 28 | static const char* portamento_strings_[]; 29 | static const char* wave_strings_[]; 30 | }; 31 | } // namespace mopo 32 | 33 | #endif // CURSYNTH_STRINGS_H 34 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2013-2015 Matt Tytel 2 | * 3 | * cursynth is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * cursynth is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with cursynth. If not, see . 15 | */ 16 | 17 | #include "cursynth.h" 18 | #include 19 | #include 20 | #include 21 | 22 | int main(int argc, char **argv) { 23 | unsigned buffer_size = mopo::DEFAULT_BUFFER_SIZE; 24 | unsigned sample_rate = mopo::DEFAULT_SAMPLE_RATE; 25 | 26 | int getopt_response = 0; 27 | int digit_optind = 0; 28 | 29 | while (getopt_response != -1) { 30 | static const struct option long_options[] = { 31 | {"sample-rate", required_argument, 0, 's'}, 32 | {"buffer-size", required_argument, 0, 'b'}, 33 | {"version", no_argument, 0, 'V'}, 34 | {0, 0, 0, 0} 35 | }; 36 | 37 | int option_index = 0; 38 | getopt_response = getopt_long(argc, argv, "s:b:V", 39 | long_options, &option_index); 40 | 41 | switch (getopt_response) { 42 | case 's': 43 | sample_rate = atoi(optarg); 44 | break; 45 | case 'b': 46 | buffer_size = atoi(optarg); 47 | break; 48 | case 'V': 49 | std::cout << "Cursynth " << VERSION << std::endl; 50 | exit(EXIT_SUCCESS); 51 | break; 52 | case -1: 53 | break; 54 | default: 55 | std::cout << std::endl << "Usage:" << std::endl 56 | << "cursynth [--buffer-size OR -b preferred-buffer-size]" 57 | << std::endl 58 | << " [--sample-rate OR -s preferred-sample-rate]" 59 | << std::endl 60 | << " [--version OR -V]" 61 | << std::endl; 62 | exit(EXIT_FAILURE); 63 | break; 64 | } 65 | } 66 | 67 | mopo::Cursynth cursynth; 68 | cursynth.start(sample_rate, buffer_size); 69 | 70 | return 0; 71 | } 72 | --------------------------------------------------------------------------------