From d7b13aad99d3f78296c30bb0aafe9465be34ef87 Mon Sep 17 00:00:00 2001 From: Thor Harald Johansen Date: Wed, 12 Apr 2023 21:28:03 +0200 Subject: [PATCH] Various changes --- CMakeLists.txt | 15 +++++---- include/synth/channel.h | 1 + include/synth/dsp/filter.h | 35 ++++++++++++--------- include/synth/dsp/util.h | 33 ++++++++++++++----- include/synth/frame.h | 41 ++++++++++++++++++++++++ include/synth/globals.h | 40 ++--------------------- include/synth/synth.h | 1 + include/synth/voice.h | 2 +- src/genluts.cpp | 52 +++++++++++++++++++----------- src/synth/channel.cpp | 1 - src/synth/dsp/centlut.cpp | 18 +++++++++++ src/synth/dsp/filterlut.cpp | 14 ++++++--- src/synth/dsp/notelut.cpp | 18 +++++++++++ src/synth/synth.cpp | 8 ++--- src/synth/voicemanager.cpp | 9 +++--- src/synthapp.cpp | 63 ++++++++++++++++++++++--------------- xctrace-command.txt | 2 +- 17 files changed, 228 insertions(+), 125 deletions(-) create mode 100644 include/synth/frame.h create mode 100644 src/synth/dsp/centlut.cpp create mode 100644 src/synth/dsp/notelut.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a8527af..3101337 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,13 @@ project(synth) set(CMAKE_CXX_STANDARD 20) set(BUILD_SHARED_LIBS OFF) +if(MSVC) + set(CMAKE_CXX_FLAGS_DEBUG "/W4 /DEBUG:FASTLINK /fp:fast") + set(CMAKE_CXX_FLAGS_RELEASE "/W4 /O2 /fp:fast /DNDEBUG") +else() + set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -ffast-math") + set(CMAKE_CXX_FLAGS_RELEASE "-Wall -Ofast -DNDEBUG") +endif() if(WIN32) option(PA_USE_ASIO "" ON) @@ -26,6 +33,8 @@ add_executable(main src/synth/channel.cpp src/synth/preset.cpp src/synth/voice.cpp + src/synth/dsp/notelut.cpp + src/synth/dsp/centlut.cpp src/synth/dsp/oscillator.cpp src/synth/dsp/filter.cpp src/synth/dsp/filterlut.cpp @@ -35,12 +44,6 @@ target_include_directories(main PRIVATE include) add_executable(genluts src/genluts.cpp) target_include_directories(genluts PRIVATE include) -if(MSVC) - target_compile_options(main PRIVATE /fp:fast) -else() - target_compile_options(main PRIVATE -ffast-math) -endif() - #target_compile_options(main PRIVATE -fsanitize=thread) #target_link_options(main PRIVATE -fsanitize=thread) diff --git a/include/synth/channel.h b/include/synth/channel.h index b72d772..4ac9163 100644 --- a/include/synth/channel.h +++ b/include/synth/channel.h @@ -8,6 +8,7 @@ #include "voicemanager.h" #include "voice.h" #include "preset.h" +#include "frame.h" class Channel { public: diff --git a/include/synth/dsp/filter.h b/include/synth/dsp/filter.h index 21de284..077d68d 100644 --- a/include/synth/dsp/filter.h +++ b/include/synth/dsp/filter.h @@ -5,27 +5,34 @@ #include #include +#include +#include "../globals.h" #include "util.h" #define FILTER_K_BASE 6.214608098422192 -#define KLUT_SIZE 64 -extern float klut[KLUT_SIZE]; - -inline float freqToK(float x) { - float intPart; - float fracPart = modf(x * (KLUT_SIZE - 1), &intPart); - int index = (int) intPart; - if(fracPart < FLT_EPSILON) { - return klut[index]; - } else { - return (1 - fracPart) * klut[index] + fracPart * klut[index + 1]; +#ifdef USE_LUTS + + #define K_LUT_SIZE 64 + + extern float kLUT[K_LUT_SIZE]; + + inline float freqToK(float x) { + float intPart, fracPart = modf(x * (K_LUT_SIZE - 1), &intPart); + int index = (int) intPart; + return fracPart < FLT_EPSILON ? kLUT[index] : (1 - fracPart) * kLUT[index] + fracPart * kLUT[index + 1]; } - return klut[(int) roundf((KLUT_SIZE - 1) * x)]; -} -inline float noteToK(float note) { +#else + + inline float freqToK(float x) { + return tan(M_PI_4 * 0.002 * exp(x * FILTER_K_BASE)); + } + +#endif + +inline float noteToFltFreq(float note) { return ((note - 69) / 12.0) / (FILTER_K_BASE * M_LOG2E); } diff --git a/include/synth/dsp/util.h b/include/synth/dsp/util.h index a40509f..e9a8bce 100644 --- a/include/synth/dsp/util.h +++ b/include/synth/dsp/util.h @@ -2,19 +2,36 @@ #define __UTIL_H__ #include +#include + +#include "../globals.h" #define PIx2 (2 * M_PI) -inline float clamp(float x, float a, float b) { - return fminf(b, fmaxf(a, x)); -} +#ifdef USE_LUTS -inline float dBToGain(float dB) { - return pow(10, dB / 20.0); -} + #define NOTE_LUT_SIZE 128 + #define CENT_LUT_SIZE 128 + + extern float noteLUT[NOTE_LUT_SIZE]; + extern float centLUT[CENT_LUT_SIZE]; + + inline float noteToFreq(float note) { + float intPart, fracPart = modf(note, &intPart); + int index = (int) intPart; + return fracPart < FLT_EPSILON ? noteLUT[index] : noteLUT[index] * centLUT[(int) (fracPart * 127.0)]; + } + +#else + + inline float noteToFreq(float note) { + return 440 * pow(2, (note - 69) / 12.0); + } -inline float noteToFreq(float note) { - return 440 * pow(2, (note - 69) / 12.0); +#endif + +inline float clamp(float x, float a, float b) { + return fminf(b, fmaxf(a, x)); } inline float triangle(float phase) { diff --git a/include/synth/frame.h b/include/synth/frame.h new file mode 100644 index 0000000..80af2fd --- /dev/null +++ b/include/synth/frame.h @@ -0,0 +1,41 @@ +#ifndef __FRAME_H__ +#define __FRAME_H__ + +struct frame { + float left; + float right; + + inline frame operator+(const frame& rhs) { + return { + .left = left + rhs.left, + .right = right + rhs.right + }; + } + + inline frame operator+=(const frame& rhs) { + this->left += rhs.left; + this->right += rhs.right; + return *this; + } + + inline frame operator*(float rhs) { + return { + .left = left * rhs, + .right = right * rhs + }; + } + + inline frame operator+=(float rhs) { + this->left += rhs; + this->right += rhs; + return *this; + } + + inline frame operator*=(float rhs) { + this->left *= rhs; + this->right *= rhs; + return *this; + } +}; + +#endif \ No newline at end of file diff --git a/include/synth/globals.h b/include/synth/globals.h index 03787cf..c821608 100644 --- a/include/synth/globals.h +++ b/include/synth/globals.h @@ -1,44 +1,8 @@ #ifndef __GLOBALS_H__ #define __GLOBALS_H__ -#define SAMPLE_RATE 48000 +#define SAMPLE_RATE 44100 -struct frame { - float left; - float right; - - inline frame operator+(const frame& rhs) { - return { - .left = left + rhs.left, - .right = right + rhs.right - }; - } - - inline frame operator+=(const frame& rhs) { - this->left += rhs.left; - this->right += rhs.right; - return *this; - } - - inline frame operator*(float rhs) { - return { - .left = left * rhs, - .right = right * rhs - }; - } - - inline frame operator+=(float rhs) { - this->left += rhs; - this->right += rhs; - return *this; - } - - - inline frame operator*=(float rhs) { - this->left *= rhs; - this->right *= rhs; - return *this; - } -}; +//#define USE_LUTS #endif \ No newline at end of file diff --git a/include/synth/synth.h b/include/synth/synth.h index da19201..8cadb02 100644 --- a/include/synth/synth.h +++ b/include/synth/synth.h @@ -3,6 +3,7 @@ #include "voicemanager.h" #include "channel.h" +#include "frame.h" class Synth { public: diff --git a/include/synth/voice.h b/include/synth/voice.h index cc2235b..a860f2c 100644 --- a/include/synth/voice.h +++ b/include/synth/voice.h @@ -53,7 +53,7 @@ public: float out = 0; out += (1 - settings->oscMix) * osc1.tick(osc1PhaseStep); out += settings->oscMix * osc2.tick(osc2PhaseStep); - const float keyTrackVal = settings->keyTrack * noteToK(note); + const float keyTrackVal = settings->keyTrack * noteToFltFreq(note); out = filter.tick(out, settings->modEnvFltGain * adsrMod.tick() + keyTrackVal + fltFreqAdd); out *= adsrAmp.tick(); return out; diff --git a/src/genluts.cpp b/src/genluts.cpp index 9fe4e4f..21fc7bd 100644 --- a/src/genluts.cpp +++ b/src/genluts.cpp @@ -1,30 +1,46 @@ -#include -#include +#include +#include -#include "synth/dsp/filter.h" - -int main(int argc, char** argv) { - FILE* f; +#define USE_LUTS - float klut[KLUT_SIZE]; - for(int i = 0; i < KLUT_SIZE; ++i) { - klut[i] = tan(M_PI_4 * 0.002 * exp(i / (KLUT_SIZE - 1.0) * FILTER_K_BASE)); - } +#include "synth/dsp/filter.h" +#include "synth/dsp/util.h" - f = fopen("src/synth/dsp/filterlut.cpp", "w"); - fputs("float klut[] = {\n", f); - for(int i = 0; i < KLUT_SIZE; ++i) { - if(i % 16 == 0) { +void dumpLUT(const char * filename, const char * identifier, float *lut, size_t size) { + FILE * f = fopen(filename, "w"); + fprintf(f, "float %s[] = {\n", identifier); + for(int i = 0; i < size; ++i) { + if(i % 8 == 0) { fputs(" ", f); } - fprintf(f, "%.7f", klut[i]); - if(i < KLUT_SIZE - 1) { + fprintf(f, "%13.7f", lut[i]); + if(i < size - 1) { fputs(", ", f); } - if(i % 16 == 15) { + if(i % 8 == 7) { putc('\n', f); } } fputs("};\n", f); - fclose(f); + fclose(f); +} + +int main(int argc, char** argv) { + float kLUT[K_LUT_SIZE]; + for(int i = 0; i < K_LUT_SIZE; ++i) { + kLUT[i] = tan(M_PI_4 * 0.002 * exp(i / (K_LUT_SIZE - 1.0) * FILTER_K_BASE)); + } + dumpLUT("src/synth/dsp/filterlut.cpp", "kLUT", kLUT, K_LUT_SIZE); + + float noteLUT[NOTE_LUT_SIZE]; + for(int i = 0; i < NOTE_LUT_SIZE; ++i) { + noteLUT[i] = 440 * pow(2, (i - 69) / 12.0); + } + dumpLUT("src/synth/dsp/notelut.cpp", "noteLUT", noteLUT, NOTE_LUT_SIZE); + + float centLUT[CENT_LUT_SIZE]; + for(int i = 0; i < CENT_LUT_SIZE; ++i) { + centLUT[i] = pow(2, (float) i / ((CENT_LUT_SIZE - 1) * 12.0)); + } + dumpLUT("src/synth/dsp/centlut.cpp", "centLUT", centLUT, CENT_LUT_SIZE); } \ No newline at end of file diff --git a/src/synth/channel.cpp b/src/synth/channel.cpp index 3134347..a56b89f 100644 --- a/src/synth/channel.cpp +++ b/src/synth/channel.cpp @@ -93,7 +93,6 @@ void Channel::control(int code, int value) { case CC_FLT_Q: // Timbre / Harmonic Content (Standard MIDI) settings.filter.res = value / 31.75; - std::cout << "Q=" << settings.filter.res << std::endl; break; case CC_AMP_REL: // Release Time (Standard MIDI) diff --git a/src/synth/dsp/centlut.cpp b/src/synth/dsp/centlut.cpp new file mode 100644 index 0000000..efcdb00 --- /dev/null +++ b/src/synth/dsp/centlut.cpp @@ -0,0 +1,18 @@ +float centLUT[] = { + 1.0000000, 1.0004549, 1.0009100, 1.0013654, 1.0018209, 1.0022767, 1.0027326, 1.0031888, + 1.0036452, 1.0041018, 1.0045586, 1.0050156, 1.0054728, 1.0059302, 1.0063878, 1.0068456, + 1.0073037, 1.0077620, 1.0082204, 1.0086790, 1.0091379, 1.0095969, 1.0100563, 1.0105158, + 1.0109755, 1.0114354, 1.0118955, 1.0123559, 1.0128164, 1.0132772, 1.0137382, 1.0141994, + 1.0146607, 1.0151223, 1.0155841, 1.0160462, 1.0165083, 1.0169708, 1.0174334, 1.0178963, + 1.0183593, 1.0188227, 1.0192862, 1.0197498, 1.0202137, 1.0206778, 1.0211421, 1.0216067, + 1.0220715, 1.0225364, 1.0230016, 1.0234669, 1.0239326, 1.0243984, 1.0248644, 1.0253307, + 1.0257971, 1.0262637, 1.0267307, 1.0271977, 1.0276650, 1.0281326, 1.0286002, 1.0290682, + 1.0295364, 1.0300047, 1.0304732, 1.0309421, 1.0314111, 1.0318803, 1.0323497, 1.0328194, + 1.0332892, 1.0337592, 1.0342295, 1.0347000, 1.0351708, 1.0356417, 1.0361128, 1.0365841, + 1.0370557, 1.0375276, 1.0379995, 1.0384717, 1.0389441, 1.0394168, 1.0398897, 1.0403627, + 1.0408360, 1.0413095, 1.0417832, 1.0422572, 1.0427313, 1.0432056, 1.0436803, 1.0441550, + 1.0446301, 1.0451053, 1.0455807, 1.0460564, 1.0465323, 1.0470084, 1.0474846, 1.0479612, + 1.0484380, 1.0489149, 1.0493921, 1.0498694, 1.0503471, 1.0508249, 1.0513029, 1.0517812, + 1.0522597, 1.0527384, 1.0532173, 1.0536964, 1.0541759, 1.0546554, 1.0551351, 1.0556152, + 1.0560954, 1.0565759, 1.0570565, 1.0575374, 1.0580184, 1.0584998, 1.0589813, 1.0594631 +}; diff --git a/src/synth/dsp/filterlut.cpp b/src/synth/dsp/filterlut.cpp index 4ae39d8..4ea7d28 100644 --- a/src/synth/dsp/filterlut.cpp +++ b/src/synth/dsp/filterlut.cpp @@ -1,6 +1,10 @@ -float klut[] = { - 0.0015708, 0.0017336, 0.0019134, 0.0021118, 0.0023307, 0.0025723, 0.0028390, 0.0031333, 0.0034582, 0.0038167, 0.0042124, 0.0046491, 0.0051311, 0.0056631, 0.0062502, 0.0068982, - 0.0076134, 0.0084028, 0.0092740, 0.0102355, 0.0112968, 0.0124681, 0.0137608, 0.0151877, 0.0167625, 0.0185007, 0.0204193, 0.0225369, 0.0248743, 0.0274544, 0.0303024, 0.0334462, - 0.0369167, 0.0407480, 0.0449779, 0.0496483, 0.0548053, 0.0605004, 0.0667905, 0.0737388, 0.0814158, 0.0898997, 0.0992782, 0.1096492, 0.1211226, 0.1338222, 0.1478880, 0.1634790, - 0.1807770, 0.1999912, 0.2213640, 0.2451794, 0.2717728, 0.3015462, 0.3349871, 0.3726965, 0.4154281, 0.4641461, 0.5201120, 0.5850177, 0.6611994, 0.7519926, 0.8623521, 1.0000000 +float kLUT[] = { + 0.0015708, 0.0017336, 0.0019134, 0.0021118, 0.0023307, 0.0025723, 0.0028390, 0.0031333, + 0.0034582, 0.0038167, 0.0042124, 0.0046491, 0.0051311, 0.0056631, 0.0062502, 0.0068982, + 0.0076134, 0.0084028, 0.0092740, 0.0102355, 0.0112968, 0.0124681, 0.0137608, 0.0151877, + 0.0167625, 0.0185007, 0.0204193, 0.0225369, 0.0248743, 0.0274544, 0.0303024, 0.0334462, + 0.0369167, 0.0407480, 0.0449779, 0.0496483, 0.0548053, 0.0605004, 0.0667905, 0.0737388, + 0.0814158, 0.0898997, 0.0992782, 0.1096492, 0.1211226, 0.1338222, 0.1478880, 0.1634790, + 0.1807770, 0.1999912, 0.2213640, 0.2451794, 0.2717728, 0.3015462, 0.3349871, 0.3726965, + 0.4154281, 0.4641461, 0.5201120, 0.5850177, 0.6611994, 0.7519926, 0.8623521, 1.0000000 }; diff --git a/src/synth/dsp/notelut.cpp b/src/synth/dsp/notelut.cpp new file mode 100644 index 0000000..952bca2 --- /dev/null +++ b/src/synth/dsp/notelut.cpp @@ -0,0 +1,18 @@ +float noteLUT[] = { + 8.1757994, 8.6619568, 9.1770239, 9.7227182, 10.3008614, 10.9133825, 11.5623255, 12.2498569, + 12.9782715, 13.7500000, 14.5676174, 15.4338531, 16.3515987, 17.3239136, 18.3540478, 19.4454365, + 20.6017227, 21.8267651, 23.1246510, 24.4997139, 25.9565430, 27.5000000, 29.1352348, 30.8677063, + 32.7031975, 34.6478271, 36.7080956, 38.8908730, 41.2034454, 43.6535301, 46.2493019, 48.9994278, + 51.9130859, 55.0000000, 58.2704697, 61.7354126, 65.4063950, 69.2956543, 73.4161911, 77.7817459, + 82.4068909, 87.3070602, 92.4986038, 97.9988556, 103.8261719, 110.0000000, 116.5409393, 123.4708252, + 130.8127899, 138.5913086, 146.8323822, 155.5634918, 164.8137817, 174.6141205, 184.9972076, 195.9977112, + 207.6523438, 220.0000000, 233.0818787, 246.9416504, 261.6255798, 277.1826172, 293.6647644, 311.1269836, + 329.6275635, 349.2282410, 369.9944153, 391.9954224, 415.3046875, 440.0000000, 466.1637573, 493.8833008, + 523.2511597, 554.3652344, 587.3295288, 622.2539673, 659.2551270, 698.4564819, 739.9888306, 783.9908447, + 830.6093750, 880.0000000, 932.3275146, 987.7666016, 1046.5023193, 1108.7304688, 1174.6590576, 1244.5079346, + 1318.5102539, 1396.9129639, 1479.9776611, 1567.9816895, 1661.2187500, 1760.0000000, 1864.6550293, 1975.5332031, + 2093.0046387, 2217.4609375, 2349.3181152, 2489.0158691, 2637.0205078, 2793.8259277, 2959.9553223, 3135.9633789, + 3322.4375000, 3520.0000000, 3729.3100586, 3951.0664062, 4186.0092773, 4434.9218750, 4698.6362305, 4978.0317383, + 5274.0410156, 5587.6518555, 5919.9106445, 6271.9267578, 6644.8750000, 7040.0000000, 7458.6201172, 7902.1328125, + 8372.0185547, 8869.8437500, 9397.2724609, 9956.0634766, 10548.0820312, 11175.3037109, 11839.8212891, 12543.8535156 +}; diff --git a/src/synth/synth.cpp b/src/synth/synth.cpp index a909d7a..47b2275 100644 --- a/src/synth/synth.cpp +++ b/src/synth/synth.cpp @@ -1,18 +1,18 @@ -#include +#include #include "synth/synth.h" void Synth::noteOn(int ch, int note, int vel) { channels[ch].noteOn(note, vel); - std::cout << "Note On: ch=" << ch << " note=" << note << " vel=" << vel << std::endl; + printf("Note On: ch=%d note=%d vel=%d\n", ch, note, vel); } void Synth::noteOff(int ch, int note) { channels[ch].noteOff(note); - std::cout << "Note Off: ch=" << ch << " note=" << note << std::endl; + printf("Note Off: ch=%d note=%d\n", ch, note); } void Synth::control(int ch, int cc, int val) { channels[ch].control(cc, val); - std::cout << "Controller: ch=" << ch << " cc=" << cc << " val=" << val << std::endl; + printf("Controller: ch=%d cc=%d val=%d\n", ch, cc, val); } \ No newline at end of file diff --git a/src/synth/voicemanager.cpp b/src/synth/voicemanager.cpp index bf4f4e6..76a1282 100644 --- a/src/synth/voicemanager.cpp +++ b/src/synth/voicemanager.cpp @@ -1,4 +1,4 @@ -#include +#include #include "synth/voicemanager.h" @@ -20,10 +20,11 @@ Voice * VoiceManager::get(channel_t channel) { voiceData.serial = serial++; voiceData.voice.reset(); + putchar('\n'); for(VoiceData& vd : voices) { - std::cout << "channel=" << vd.channel << " serial=" << vd.serial << " idle=" << vd.voice.isIdle() << " note=" << vd.voice.note << std::endl; + printf("channel=%d serial=%d idle=%d note=%d\n", vd.channel, vd.serial, vd.voice.isIdle(), vd.voice.note); } - std::cout << std::endl; + putchar('\n'); return &voiceData.voice; } @@ -38,4 +39,4 @@ Voice** VoiceManager::getChannelVoices(channel_t channel) { } *voice = NULL; return result; -} \ No newline at end of file +} diff --git a/src/synthapp.cpp b/src/synthapp.cpp index fad60db..97e86fa 100644 --- a/src/synthapp.cpp +++ b/src/synthapp.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include #include "synth/globals.h" @@ -10,6 +10,7 @@ using namespace std; // PortAudio callback for audio I/O +bool firstPACallback = true; static int paCallback( const void *inputBuffer, void *outputBuffer, @@ -20,6 +21,11 @@ static int paCallback( SynthApp *app = (SynthApp*) userData; + if(firstPACallback) { + printf("Buffer size is %ld frames\n", framesPerBuffer); + firstPACallback = false; + } + PmEvent events[16]; int numEvents = Pm_Read(app->pmStream, events, 16); for(int i = 0; i < numEvents; ++i) { @@ -40,13 +46,6 @@ static int paCallback( int val = Pm_MessageData2(msg); app->synth.control(ch, cc, val); } - /* - cout << "MIDI:"; - for(int j = 0; j < 24; j += 8) { - cout << " " << hex << ((msg >> j) & 0xFF); - } - cout << endl; - */ } float *out = (float*) outputBuffer; @@ -90,19 +89,22 @@ bool SynthApp::OnInit() { } int pmDeviceCount = Pm_CountDevices(); - cout << "Select MIDI input device:" << endl; + putchar('\n'); + printf("Select MIDI input device:\n\n"); for(int i = 0; i < pmDeviceCount; ++i) { const PmDeviceInfo* deviceInfo = Pm_GetDeviceInfo(i); if(!deviceInfo->input) { continue; } - cout << i << ". " << deviceInfo->name << endl; + printf("%d. %s\n", i, deviceInfo->name); } + putchar('\n'); int pmDeviceIndex; for(;;) { // loop for input until valid choice is made - string input; - getline(cin, input); - //string input = "1"; + printf("Number: "); + char input[4]; + fgets(input, 4, stdin); + //const char* input = "1"; try { pmDeviceIndex = stoi(input); if( pmDeviceIndex >= 0 && @@ -111,23 +113,27 @@ bool SynthApp::OnInit() { break; } } catch(...) { } // stoi() throws an exeption for invalid integers - cout << "Invalid selection" << endl; + printf("Invalid selection\n"); } + putchar('\n'); + PaHostApiIndex paDeviceCount = Pa_GetDeviceCount(); - cout << "Select audio output device:" << endl; + printf("Select audio output device:\n\n"); for(int i = 0; i < paDeviceCount; ++i) { const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(i); if(deviceInfo->maxOutputChannels < 2) { continue; } - cout << i << ". " << deviceInfo->name << " (" << Pa_GetHostApiInfo(deviceInfo->hostApi)->name << ")" << endl; + printf("%d. %s (%s)\n", i, deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name); } + putchar('\n'); PaHostApiIndex paDeviceIndex; for(;;) { // loop for input until valid choice is made - string input; - getline(cin, input); - //string input = "4"; + printf("Number: "); + char input[4]; + fgets(input, 4, stdin); + //const char* input = "5"; try { paDeviceIndex = stoi(input); if( paDeviceIndex >= 0 && @@ -136,11 +142,11 @@ bool SynthApp::OnInit() { break; } } catch(...) { } // stoi() throws an exeption for invalid integers - cout << "Invalid selection" << endl; + printf("Invalid selection\n"); } // Open MIDI input - PmError pmError = Pm_OpenInput( + pmErr = Pm_OpenInput( &pmStream, pmDeviceIndex, NULL, @@ -151,18 +157,25 @@ bool SynthApp::OnInit() { handlePMError(pmErr); } + const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(paDeviceIndex); + + putchar('\n'); + printf("Default sample rate is %.0f Hz\n", deviceInfo->defaultSampleRate); + printf("Default low input latency is %.0f samples\n", deviceInfo->defaultSampleRate * deviceInfo->defaultLowOutputLatency); + putchar('\n'); + // Configure/start audio output stream PaStreamParameters paStreamParams; paStreamParams.device = paDeviceIndex; paStreamParams.channelCount = 2; paStreamParams.sampleFormat = paFloat32; - paStreamParams.suggestedLatency = 512.0 / SAMPLE_RATE; + paStreamParams.suggestedLatency = deviceInfo->defaultLowOutputLatency; paStreamParams.hostApiSpecificStreamInfo = NULL; paErr = Pa_OpenStream( &paStream, NULL, // no input channels &paStreamParams, // stereo output - SAMPLE_RATE, + deviceInfo->defaultSampleRate, 0, // frames per buffer paNoFlag, paCallback, @@ -176,7 +189,7 @@ bool SynthApp::OnInit() { } const PaStreamInfo *paStreamInfo = Pa_GetStreamInfo(paStream); - cout << "Latency: " << round(1000 * paStreamInfo->outputLatency) << " ms" << endl; + printf("Reported latency is %d frames\n", (int) round(SAMPLE_RATE * paStreamInfo->outputLatency)); wxFrame *frame = new SynthFrame(); frame->Show(true); @@ -197,7 +210,7 @@ int SynthApp::OnExit() { handlePMError(pmErr); } Pa_Terminate(); - cout << "Terminating" << endl; + printf("\nTerminating\n"); return 0; } diff --git a/xctrace-command.txt b/xctrace-command.txt index b23f5a7..0832b40 100644 --- a/xctrace-command.txt +++ b/xctrace-command.txt @@ -1 +1 @@ - xctrace record --template 'Time Profiler' --target-stdin - --target-stdout - --launch ./build/main \ No newline at end of file +xctrace record --template 'Time Profiler' --launch ./build/main \ No newline at end of file