diff --git a/src/core/source/SineWaveNoteSynthesizer.cpp b/src/core/source/NoteSynthesizer.cpp similarity index 57% rename from src/core/source/SineWaveNoteSynthesizer.cpp rename to src/core/source/NoteSynthesizer.cpp index 0b8769f..f125fc3 100644 --- a/src/core/source/SineWaveNoteSynthesizer.cpp +++ b/src/core/source/NoteSynthesizer.cpp @@ -21,35 +21,78 @@ #include -#include "SineWaveNoteSynthesizer.h" -#include "SineWaveNoteSynthesizer_p.h" +#include "NoteSynthesizer.h" +#include "NoteSynthesizer_p.h" namespace talcs { - SineWaveNoteSynthesizer::SineWaveNoteSynthesizer() : SineWaveNoteSynthesizer(*new SineWaveNoteSynthesizerPrivate) { + NoteSynthesizer::NoteSynthesizer() : NoteSynthesizer(*new NoteSynthesizerPrivate) { } - SineWaveNoteSynthesizer::SineWaveNoteSynthesizer(SineWaveNoteSynthesizerPrivate &d) : AudioSource(d) { + NoteSynthesizer::NoteSynthesizer(NoteSynthesizerPrivate &d) : AudioSource(d) { } - SineWaveNoteSynthesizer::~SineWaveNoteSynthesizer() { + NoteSynthesizer::~NoteSynthesizer() { } - bool SineWaveNoteSynthesizer::open(qint64 bufferSize, double sampleRate) { - Q_D(SineWaveNoteSynthesizer); - d->rate = std::pow(0.99, 20000.0 / sampleRate); + bool NoteSynthesizer::open(qint64 bufferSize, double sampleRate) { + Q_D(NoteSynthesizer); return AudioSource::open(bufferSize, sampleRate); } - void SineWaveNoteSynthesizer::close() { + void NoteSynthesizer::close() { AudioSource::close(); } - qint64 SineWaveNoteSynthesizer::processReading(const AudioSourceReadData &readData) { - static const double PI = std::acos(-1); - Q_D(SineWaveNoteSynthesizer); + void NoteSynthesizer::setAttackRate(double rate) { + Q_D(NoteSynthesizer); + d->attackRate = rate; + } + + double NoteSynthesizer::attackRate() const { + Q_D(const NoteSynthesizer); + return d->attackRate; + } + + void NoteSynthesizer::setReleaseRate(double rate) { + Q_D(NoteSynthesizer); + d->releaseRate = rate; + } + + double NoteSynthesizer::releaseRate() const { + Q_D(const NoteSynthesizer); + return d->releaseRate; + } + + + void NoteSynthesizer::setGenerator(NoteSynthesizer::Generator g) { + switch (g) { + case Sine: + setGenerator(NoteSynthesizerPrivate::GenerateSineWave()); + break; + case Square: + setGenerator(NoteSynthesizerPrivate::GenerateSquareWave()); + break; + case Triangle: + setGenerator(NoteSynthesizerPrivate::GenerateTriangleWave()); + break; + case Sawtooth: + setGenerator(NoteSynthesizerPrivate::GenerateSawtoothWave()); + break; + default: + Q_UNREACHABLE(); + } + } + + void NoteSynthesizer::setGenerator(const NoteSynthesizer::GeneratorFunction &g) { + Q_D(NoteSynthesizer); + d->generatorFunction = g; + } + + qint64 NoteSynthesizer::processReading(const AudioSourceReadData &readData) { + Q_D(NoteSynthesizer); QMutexLocker locker(&d->mutex); for (int ch = 0; ch < readData.buffer->channelCount(); ch++) { readData.buffer->clear(ch, readData.startPos, readData.length); @@ -61,9 +104,9 @@ namespace talcs { for (auto msg = d->detector->nextMessage(); ; msg = d->detector->nextMessage()) { for (;currentPos < (msg.position != -1 ? msg.position : readData.length); currentPos++) { for (auto &keyInfo : d->keys) { - double vel = keyInfo.nextVel(d->rate); + double vel = keyInfo.nextVel(); for (int ch = 0; ch < readData.buffer->channelCount(); ch++) { - readData.buffer->sampleAt(ch, readData.startPos + currentPos) += vel * std::sin(2.0 * PI * keyInfo.frequency / sampleRate() * double(keyInfo.x)); + readData.buffer->sampleAt(ch, readData.startPos + currentPos) += static_cast(vel * d->generatorFunction(keyInfo.frequency / sampleRate(), keyInfo.x)); } } d->keys.erase(std::remove_if(d->keys.begin(), d->keys.end(), [&](const auto &item) { @@ -74,7 +117,7 @@ namespace talcs { return qFuzzyCompare(item.frequency, msg.frequency); }); if (msg.isNoteOn) { - d->keys.append({msg.frequency, msg.velocity, .0, 0, true}); + d->keys.append({d, msg.frequency, msg.velocity, .0, 0, true}); } else { if (it != d->keys.end()) it->isAttack = false; @@ -85,14 +128,14 @@ namespace talcs { return readData.length; } - void SineWaveNoteSynthesizer::setDetector(SineWaveNoteSynthesizerDetector *detector) { - Q_D(SineWaveNoteSynthesizer); + void NoteSynthesizer::setDetector(NoteSynthesizerDetector *detector) { + Q_D(NoteSynthesizer); QMutexLocker locker(&d->mutex); d->detector = detector; } - SineWaveNoteSynthesizerDetector *SineWaveNoteSynthesizer::detector() const { - Q_D(const SineWaveNoteSynthesizer); + NoteSynthesizerDetector *NoteSynthesizer::detector() const { + Q_D(const NoteSynthesizer); return d->detector; } } // talcs \ No newline at end of file diff --git a/src/core/source/SineWaveNoteSynthesizer.h b/src/core/source/NoteSynthesizer.h similarity index 63% rename from src/core/source/SineWaveNoteSynthesizer.h rename to src/core/source/NoteSynthesizer.h index 6d29d1a..54a3fdd 100644 --- a/src/core/source/SineWaveNoteSynthesizer.h +++ b/src/core/source/NoteSynthesizer.h @@ -17,46 +17,63 @@ * along with TALCS. If not, see . * ******************************************************************************/ -#ifndef TALCS_SINEWAVENOTESYNTHESIZER_H -#define TALCS_SINEWAVENOTESYNTHESIZER_H +#ifndef TALCS_NOTESYNTHESIZER_H +#define TALCS_NOTESYNTHESIZER_H #include namespace talcs { - struct SineWaveNoteSynthesizerDetectorMessage { + struct NoteSynthesizerDetectorMessage { qint64 position; double frequency; double velocity; bool isNoteOn; }; - class SineWaveNoteSynthesizerDetector { + class NoteSynthesizerDetector { public: virtual void detectInterval(qint64 intervalLength) = 0; - virtual SineWaveNoteSynthesizerDetectorMessage nextMessage() = 0; + virtual NoteSynthesizerDetectorMessage nextMessage() = 0; }; - class SineWaveNoteSynthesizerPrivate; + class NoteSynthesizerPrivate; - class TALCSCORE_EXPORT SineWaveNoteSynthesizer : public AudioSource { - Q_DECLARE_PRIVATE(SineWaveNoteSynthesizer) + class TALCSCORE_EXPORT NoteSynthesizer : public AudioSource { + Q_DECLARE_PRIVATE(NoteSynthesizer) public: - explicit SineWaveNoteSynthesizer(); - ~SineWaveNoteSynthesizer() override; + explicit NoteSynthesizer(); + ~NoteSynthesizer() override; bool open(qint64 bufferSize, double sampleRate) override; void close() override; - void setDetector(SineWaveNoteSynthesizerDetector *detector); - SineWaveNoteSynthesizerDetector *detector() const; + void setAttackRate(double rate); + double attackRate() const; + void setReleaseRate(double rate); + double releaseRate() const; + + enum Generator { + Sine, + Square, + Triangle, + Sawtooth, + }; + + using GeneratorFunction = std::function; + + void setGenerator(Generator); + void setGenerator(const GeneratorFunction &); + + void setDetector(NoteSynthesizerDetector *detector); + NoteSynthesizerDetector *detector() const; protected: - explicit SineWaveNoteSynthesizer(SineWaveNoteSynthesizerPrivate &d); + explicit NoteSynthesizer(NoteSynthesizerPrivate &d); qint64 processReading(const AudioSourceReadData &readData) override; }; } -#endif //TALCS_SINEWAVENOTESYNTHESIZER_H +#endif //TALCS_NOTESYNTHESIZER_H diff --git a/src/core/source/SineWaveNoteSynthesizer_p.h b/src/core/source/NoteSynthesizer_p.h similarity index 53% rename from src/core/source/SineWaveNoteSynthesizer_p.h rename to src/core/source/NoteSynthesizer_p.h index 90494a4..7fd21eb 100644 --- a/src/core/source/SineWaveNoteSynthesizer_p.h +++ b/src/core/source/NoteSynthesizer_p.h @@ -17,37 +17,39 @@ * along with TALCS. If not, see . * ******************************************************************************/ -#ifndef TALCS_SINEWAVENOTESYNTHESIZER_P_H -#define TALCS_SINEWAVENOTESYNTHESIZER_P_H +#ifndef TALCS_NoteSynthesizer_P_H +#define TALCS_NoteSynthesizer_P_H #include -#include +#include #include namespace talcs { - class SineWaveNoteSynthesizerPrivate : public AudioSourcePrivate { - Q_DECLARE_PUBLIC(SineWaveNoteSynthesizer); + class NoteSynthesizerPrivate : public AudioSourcePrivate { + Q_DECLARE_PUBLIC(NoteSynthesizer); public: QMutex mutex; - SineWaveNoteSynthesizerDetector *detector = nullptr; + NoteSynthesizerDetector *detector = nullptr; + struct KeyInfo { + NoteSynthesizerPrivate *d; double frequency; double velFactor; double vel; qint64 x; bool isAttack; - inline double nextVel(double rate_) { + inline double nextVel() { double ret = vel; if (isAttack && vel < velFactor) { if (qFuzzyIsNull(vel)) vel = .005; - vel /= rate_; + vel /= d->attackRate; if (vel > velFactor) vel = velFactor; } else { - vel *= rate_; + vel *= d->releaseRate; if (vel < .005) vel = .0; } @@ -55,10 +57,53 @@ namespace talcs { return ret; } }; - double rate = .0; + double attackRate = .005; + double releaseRate = 0; QList keys; + + struct GenerateSineWave { + inline double operator()(double f, qint64 x) { + static const double PI = std::acos(-1); + return std::sin(2.0 * PI * f * double(x)); + } + }; + + struct GenerateSquareWave { + inline double operator()(double f, qint64 x) { + double period = 1.0 / f; + double t = fmod(x, period); + return (t < period / 2) ? 1.0 : -1.0; + } + }; + + struct GenerateTriangleWave { + inline double operator()(double f, qint64 x) { + double period = 1.0 / f; + double t = fmod(x, period); + double normalized_t = t / period; + + if (normalized_t < 0.25) { + return 4.0 * normalized_t; + } else if (normalized_t < 0.75) { + return 2.0 - 4.0 * normalized_t; + } else { + return -4.0 + 4.0 * normalized_t; + } + } + }; + + struct GenerateSawtoothWave { + inline double operator()(double f, qint64 x) { + double period = 1.0 / f; + double t = fmod(x, period); + return 2.0 * (t / period) - 1.0; + } + }; + + NoteSynthesizer::GeneratorFunction generatorFunction = GenerateSineWave(); + }; } -#endif //TALCS_SINEWAVENOTESYNTHESIZER_P_H +#endif //TALCS_NoteSynthesizer_P_H diff --git a/src/midi/MidiSineWaveSynthesizer.cpp b/src/midi/MidiSineWaveSynthesizer.cpp deleted file mode 100644 index 818b8c1..0000000 --- a/src/midi/MidiSineWaveSynthesizer.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2023 CrSjimo * - * * - * This file is part of TALCS. * - * * - * TALCS is free software: you can redistribute it and/or modify it under the * - * terms of the GNU Lesser General Public License as published by the Free * - * Software Foundation, either version 3 of the License, or (at your option) * - * any later version. * - * * - * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY * - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * - * more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with TALCS. If not, see . * - ******************************************************************************/ - -#include "MidiSineWaveSynthesizer.h" -#include "MidiSineWaveSynthesizer_p.h" - -#include - -namespace talcs { - static quint16 bundlePlayData(qint8 note, qint8 vel) { - qint8 a[2] = {note, vel}; - return *reinterpret_cast(a); - } - - static void depackPlayData(quint16 playData, qint8 ¬e, qint8 &vel) { - auto a = reinterpret_cast(&playData); - note = a[0]; - vel = a[1]; - } - - static inline double freqOfKey(int key) { - return 440.0 * std::pow(2, 1.0 * (key - 69) / 12.0); - } - - MidiSineWaveSynthesizer::MidiSineWaveSynthesizer() : AudioSource(), d(new MidiSineWaveSynthesizerPrivate) { - } - - bool MidiSineWaveSynthesizer::open(qint64 bufferSize, double sampleRate) { - return AudioStreamBase::open(bufferSize, sampleRate); - } - - void MidiSineWaveSynthesizer::close() { - QMutexLocker locker(&d->mutex); - d->note = -1; - d->phase = 0; - AudioStreamBase::close(); - } - - MidiSineWaveSynthesizer::~MidiSineWaveSynthesizer() { - - } - - qint64 MidiSineWaveSynthesizer::processReading(const AudioSourceReadData &readData) { - QMutexLocker locker(&d->mutex); - static const double PI = 3.14159265358979323846; - if (d->note == -1) { - for (int ch = 0; ch < readData.buffer->channelCount(); ch++) { - readData.buffer->clear(ch, readData.startPos, readData.length); - } - } else { - double sr = sampleRate(); - double delta = 2 * PI * MidiMessage::getMidiNoteInHertz(d->note) / sr; - for (qint64 i = 0; i < readData.length; i++) { - if (d->fadeIn != 0.0) { - readData.buffer->sampleAt(0, readData.startPos + i) = std::sin(d->phase) * (1.0 * d->velocity / 127.0) * d->fadeIn; - d->fadeIn /= 0.99; - if (d->fadeIn >= 1) - d->fadeIn = 1; - } else if (d->fadeOut != 0.0) { - readData.buffer->sampleAt(0, readData.startPos + i) = std::sin(d->phase) * (1.0 * d->velocity / 127.0) * d->fadeOut; - d->fadeOut *= 0.99; - } - d->phase += delta; - } - for (int ch = 1; ch < readData.buffer->channelCount(); ch++) { - readData.buffer->setSampleRange(ch, readData.startPos, readData.length, *readData.buffer, 0, readData.startPos); - } - } - if (d->fadeIn == 0.0 && d->fadeOut <= 0.005) { - d->fadeOut = 0.0; - d->note = -1; - d->phase = 0; - } - return readData.length; - - } - - void MidiSineWaveSynthesizer::deviceWillStartCallback(MidiInputDevice *device) { - - } - - void MidiSineWaveSynthesizer::deviceStoppedCallback() { - QMutexLocker locker(&d->mutex); - d->note = -1; - d->phase = 0; - } - - void MidiSineWaveSynthesizer::workCallback(const MidiMessage &message) { - QMutexLocker locker(&d->mutex); - if (message.isNoteOn()) { - d->note = message.getNoteNumber(); - if (d->fadeIn != 0.0) { - d->fadeIn = qMin(1.0, d->fadeIn * d->velocity / message.getVelocity()); - } else if (d->fadeOut != 0.0) { - d->fadeIn = qMin(1.0, d->fadeOut * d->velocity / message.getVelocity()); - } - d->velocity = message.getVelocity(); - d->fadeOut = 0.0; - if (d->fadeIn <= 0.005) - d->fadeIn = 0.005; - } else if (message.isNoteOff() && message.getNoteNumber() == d->note) { - d->fadeOut = 1.0; - d->fadeIn = 0.0; - } else if (message.isAllNotesOff()) { - d->fadeOut = 1.0; - d->fadeIn = 0.0; - } - } - - void MidiSineWaveSynthesizer::errorCallback(const QString &errorString) { - QMutexLocker locker(&d->mutex); - d->note = -1; - d->phase = 0; - } -} // talcs \ No newline at end of file diff --git a/src/midi/MidiMessage.cpp b/src/midi/data/MidiMessage.cpp similarity index 99% rename from src/midi/MidiMessage.cpp rename to src/midi/data/MidiMessage.cpp index e76d6a0..559e2a0 100644 --- a/src/midi/MidiMessage.cpp +++ b/src/midi/data/MidiMessage.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2022-2023 CrSjimo * + * Copyright (c) 2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -17,10 +17,12 @@ * along with TALCS. If not, see . * ******************************************************************************/ +/* This file is migrated from the JUCE library -- under ISC License */ + /* ============================================================================== - This file is migrated from the JUCE library. + This file is part of the JUCE library. Copyright (c) 2022 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source diff --git a/src/midi/MidiMessage.h b/src/midi/data/MidiMessage.h similarity index 98% rename from src/midi/MidiMessage.h rename to src/midi/data/MidiMessage.h index 1084f5a..daa1b7f 100644 --- a/src/midi/MidiMessage.h +++ b/src/midi/data/MidiMessage.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -17,10 +17,12 @@ * along with TALCS. If not, see . * ******************************************************************************/ +/* This file is migrated from the JUCE library -- under ISC License */ + /* ============================================================================== - This file is migrated from the JUCE library. + This file is part of the JUCE library. Copyright (c) 2022 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source diff --git a/src/midi/MidiInputDevice.cpp b/src/midi/device/MidiInputDevice.cpp similarity index 59% rename from src/midi/MidiInputDevice.cpp rename to src/midi/device/MidiInputDevice.cpp index 82eaf5f..b772658 100644 --- a/src/midi/MidiInputDevice.cpp +++ b/src/midi/device/MidiInputDevice.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2023-2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -22,52 +22,49 @@ #include -#include - -#include "MidiInputDeviceCallback.h" +#include "MidiMessageListener.h" namespace talcs { - MidiInputDevice::MidiInputDevice(int deviceIndex, QObject *parent) : QObject(parent), d(new MidiInputDevicePrivate) { + MidiInputDevice::MidiInputDevice(int deviceIndex, QObject *parent) : QObject(parent), d_ptr(new MidiInputDevicePrivate) { + Q_D(MidiInputDevice); + d->q_ptr = this; d->portNumber = deviceIndex; try { d->midi.reset(new RtMidiIn); - setName(d->midi->getPortName(deviceIndex).c_str()); + setName(QString::fromStdString(d->midi->getPortName(deviceIndex))); } catch (RtMidiError &e) { - setErrorString(e.getMessage().c_str()); + setErrorString(QString::fromStdString(e.getMessage())); } } MidiInputDevice::~MidiInputDevice() = default; - static void rtmidiCallback(double timeStamp, std::vector *message, void *userData) { + void MidiInputDevicePrivate::rtmidiCallback(double timeStamp, std::vector *message, void *userData) { auto d = reinterpret_cast(userData); - MidiMessage msg(message->data(), message->size(), timeStamp); - std::for_each(d->listeners.begin(), d->listeners.end(), [&](MidiInputDeviceCallback *cb) { - cb->workCallback(msg); - }); + qDebug() << timeStamp; + MidiMessage msg(message->data(), static_cast(message->size()), timeStamp); + d->listener.messageCallback(msg); } - static void rtmidiErrorCallback(RtMidiError::Type type, const std::string &errorText, void *userData) { - Q_UNUSED(type); + void MidiInputDevicePrivate::rtmidiErrorCallback(RtMidiError::Type type, const std::string &errorText, void *userData) { + Q_UNUSED(type) auto d = reinterpret_cast(userData); - std::for_each(d->listeners.begin(), d->listeners.end(), [&](MidiInputDeviceCallback *cb) { - cb->errorCallback(errorText.c_str()); - }); + d->q_ptr->setErrorString(QString::fromStdString(errorText)); + d->listener.errorCallback(QString::fromStdString(errorText)); } bool MidiInputDevice::open() { + Q_D(MidiInputDevice); if (!d->midi) return false; try { d->midi->openPort(d->portNumber); d->midi->ignoreTypes(false, false, false); - std::for_each(d->listeners.begin(), d->listeners.end(), [&](MidiInputDeviceCallback *cb) { - cb->deviceWillStartCallback(this); - }); - d->midi->setCallback(&rtmidiCallback, d.data()); - d->midi->setErrorCallback(&rtmidiErrorCallback, d.data()); + d->listener.deviceWillStartCallback(this); + d->midi->setCallback(&MidiInputDevicePrivate::rtmidiCallback, d); + d->midi->setErrorCallback(&MidiInputDevicePrivate::rtmidiErrorCallback, d); } catch (RtMidiError &e) { - setErrorString(e.getMessage().c_str()); + setErrorString(QString::fromStdString(e.getMessage())); return false; } setErrorString({}); @@ -75,37 +72,34 @@ namespace talcs { } bool MidiInputDevice::isOpen() const { + Q_D(const MidiInputDevice); return d->midi && d->midi->isPortOpen(); } void MidiInputDevice::close() { + Q_D(MidiInputDevice); if (d->midi) d->midi->closePort(); - std::for_each(d->listeners.begin(), d->listeners.end(), [&](MidiInputDeviceCallback *cb) { - cb->deviceStoppedCallback(); - }); + d->listener.deviceStoppedCallback(); setErrorString({}); } - void MidiInputDevice::addListener(MidiInputDeviceCallback *callback) { - d->listeners.append(callback); - } - - void MidiInputDevice::removeListener(MidiInputDeviceCallback *callback) { - d->listeners.removeOne(callback); + MidiMessageListener *MidiInputDevice::listener() const { + Q_D(const MidiInputDevice); + return &d->listener; } QStringList MidiInputDevice::devices() { QStringList a; try { RtMidiIn tmp; - int count = tmp.getPortCount(); + int count = static_cast(tmp.getPortCount()); a.reserve(count); for (int i = 0; i < count; i++) { - a.append(tmp.getPortName(i).c_str()); + a.append(QString::fromStdString(tmp.getPortName(i))); } } catch (RtMidiError &e) { - qWarning() << "MidiInputDevice:" << e.getMessage().c_str(); + qWarning() << "MidiInputDevice:" << QString::fromStdString(e.getMessage()); } return a; } diff --git a/src/midi/MidiInputDevice.h b/src/midi/device/MidiInputDevice.h similarity index 87% rename from src/midi/MidiInputDevice.h rename to src/midi/device/MidiInputDevice.h index c189248..398308f 100644 --- a/src/midi/MidiInputDevice.h +++ b/src/midi/device/MidiInputDevice.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2023-2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -28,27 +28,27 @@ namespace talcs { - class MidiInputDeviceCallback; + class MidiMessageListener; class MidiInputDevicePrivate; class TALCSMIDI_EXPORT MidiInputDevice : public QObject, public NameProvider, public ErrorStringProvider { Q_OBJECT + Q_DECLARE_PRIVATE(MidiInputDevice) public: explicit MidiInputDevice(int deviceIndex, QObject *parent = nullptr); - ~MidiInputDevice(); + ~MidiInputDevice() override; bool open(); bool isOpen() const; void close(); - void addListener(MidiInputDeviceCallback *callback); - void removeListener(MidiInputDeviceCallback *callback); + MidiMessageListener *listener() const; static QStringList devices(); private: - QScopedPointer d; + QScopedPointer d_ptr; }; } // talcs diff --git a/src/midi/device/MidiInputDevice_p.h b/src/midi/device/MidiInputDevice_p.h new file mode 100644 index 0000000..2153f20 --- /dev/null +++ b/src/midi/device/MidiInputDevice_p.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * Copyright (c) 2023-2024 CrSjimo * + * * + * This file is part of TALCS. * + * * + * TALCS is free software: you can redistribute it and/or modify it under the * + * terms of the GNU Lesser General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * + * more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with TALCS. If not, see . * + ******************************************************************************/ + +#ifndef TALCS_MIDIINPUTDEVICE_P_H +#define TALCS_MIDIINPUTDEVICE_P_H + +#include + +#include + +#include + +class RtMidiIn; + +namespace talcs { + + class MidiInputDeviceRootListener : public MidiMessageListener { + protected: + bool processDeviceWillStart(MidiInputDevice *device) override { + return true; + } + + void processDeviceStopped() override { + } + + bool processMessage(const MidiMessage &message) override { + return false; + } + + void processError(const QString &errorString) override { + + } + }; + + class MidiInputDevicePrivate { + Q_DECLARE_PUBLIC(MidiInputDevice) + public: + MidiInputDevice *q_ptr; + int portNumber; + QScopedPointer midi; + mutable MidiInputDeviceRootListener listener; + + static void rtmidiCallback(double timeStamp, std::vector *message, void *userData); + static void rtmidiErrorCallback(RtMidiError::Type type, const std::string &errorText, void *userData); + }; +} + +#endif //TALCS_MIDIINPUTDEVICE_P_H diff --git a/src/midi/device/MidiMessageListener.cpp b/src/midi/device/MidiMessageListener.cpp new file mode 100644 index 0000000..5cb6202 --- /dev/null +++ b/src/midi/device/MidiMessageListener.cpp @@ -0,0 +1,81 @@ +/****************************************************************************** + * Copyright (c) 2023-2024 CrSjimo * + * * + * This file is part of TALCS. * + * * + * TALCS is free software: you can redistribute it and/or modify it under the * + * terms of the GNU Lesser General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * + * more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with TALCS. If not, see . * + ******************************************************************************/ + +#include "MidiMessageListener.h" +#include "MidiMessageListener_p.h" + +#include + +namespace talcs { + MidiMessageListener::MidiMessageListener() : MidiMessageListener(*new MidiMessageListenerPrivate) { + + } + + MidiMessageListener::~MidiMessageListener() = default; + + bool MidiMessageListener::deviceWillStartCallback(MidiInputDevice *device) { + Q_D(MidiMessageListener); + QMutexLocker locker(&d->filterMutex); + return std::all_of(d->filters.cbegin(), d->filters.cend(), [device](MidiMessageListener *filter) { + return filter->deviceWillStartCallback(device); + }) && processDeviceWillStart(device); + } + + void MidiMessageListener::deviceStoppedCallback() { + Q_D(MidiMessageListener); + QMutexLocker locker(&d->filterMutex); + std::for_each(d->filters.cbegin(), d->filters.cend(), [](MidiMessageListener *filter) { + filter->deviceStoppedCallback(); + }); + processDeviceStopped(); + } + + bool MidiMessageListener::messageCallback(const MidiMessage &message) { + Q_D(MidiMessageListener); + QMutexLocker locker(&d->filterMutex); + return std::any_of(d->filters.cbegin(), d->filters.cend(), [&message](MidiMessageListener *filter) { + return filter->messageCallback(message); + }) && processMessage(message); + } + + void MidiMessageListener::errorCallback(const QString &errorString) { + Q_D(MidiMessageListener); + QMutexLocker locker(&d->filterMutex); + std::for_each(d->filters.cbegin(), d->filters.cend(), [&errorString](MidiMessageListener *filter) { + filter->errorCallback(errorString); + }); + processError(errorString); + } + + void MidiMessageListener::addFilter(MidiMessageListener *filter) { + Q_D(MidiMessageListener); + QMutexLocker locker(&d->filterMutex); + d->filters.append(filter); + } + + void MidiMessageListener::removeFilter(MidiMessageListener *filter) { + Q_D(MidiMessageListener); + QMutexLocker locker(&d->filterMutex); + d->filters.removeOne(filter); + } + + MidiMessageListener::MidiMessageListener(MidiMessageListenerPrivate &d) : d_ptr(&d) { + d.q_ptr = this; + } +} // talcs \ No newline at end of file diff --git a/src/midi/device/MidiMessageListener.h b/src/midi/device/MidiMessageListener.h new file mode 100644 index 0000000..3ff2ac4 --- /dev/null +++ b/src/midi/device/MidiMessageListener.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright (c) 2023-2024 CrSjimo * + * * + * This file is part of TALCS. * + * * + * TALCS is free software: you can redistribute it and/or modify it under the * + * terms of the GNU Lesser General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * + * more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with TALCS. If not, see . * + ******************************************************************************/ + +#ifndef TALCS_MIDIMESSAGELISTENER_H +#define TALCS_MIDIMESSAGELISTENER_H + +#include + +#include + +namespace talcs { + + class MidiInputDevice; + + class MidiMessageListenerPrivate; + + class TALCSMIDI_EXPORT MidiMessageListener { + Q_DECLARE_PRIVATE(MidiMessageListener) + public: + explicit MidiMessageListener(); + virtual ~MidiMessageListener(); + + bool deviceWillStartCallback(MidiInputDevice *device); + void deviceStoppedCallback(); + bool messageCallback(const MidiMessage &message); + void errorCallback(const QString &errorString); + + void addFilter(MidiMessageListener *filter); + void removeFilter(MidiMessageListener *filter); + + protected: + virtual bool processDeviceWillStart(MidiInputDevice *device) = 0; + virtual void processDeviceStopped() = 0; + virtual bool processMessage(const MidiMessage &message) = 0; + virtual void processError(const QString &errorString) = 0; + + explicit MidiMessageListener(MidiMessageListenerPrivate &d); + + QScopedPointer d_ptr; + + }; + +} // talcs + +#endif //TALCS_MIDIMESSAGELISTENER_H diff --git a/src/midi/MidiSineWaveSynthesizer_p.h b/src/midi/device/MidiMessageListener_p.h similarity index 76% rename from src/midi/MidiSineWaveSynthesizer_p.h rename to src/midi/device/MidiMessageListener_p.h index 95afdfb..b01014c 100644 --- a/src/midi/MidiSineWaveSynthesizer_p.h +++ b/src/midi/device/MidiMessageListener_p.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -17,24 +17,24 @@ * along with TALCS. If not, see . * ******************************************************************************/ -#ifndef TALCS_MIDISINEWAVESYNTHESIZER_P_H -#define TALCS_MIDISINEWAVESYNTHESIZER_P_H +#ifndef TALCS_MIDIMESSAGELISTENER_P_H +#define TALCS_MIDIMESSAGELISTENER_P_H +#include #include -#include +#include namespace talcs { - class MidiSineWaveSynthesizerPrivate { - public: - QMutex mutex; - double phase = 0; - int note = -1; - int velocity = 0; - double fadeIn = 0.0; - double fadeOut = 0.0; + class MidiMessageListenerPrivate { + Q_DECLARE_PUBLIC(MidiMessageListener) + public: + MidiMessageListener *q_ptr; + QList filters; + QMutex filterMutex; }; + } -#endif //TALCS_MIDISINEWAVESYNTHESIZER_P_H +#endif //TALCS_MIDIMESSAGELISTENER_P_H diff --git a/src/midi/integrator/AbstractMidiMessageIntegrator.cpp b/src/midi/integrator/AbstractMidiMessageIntegrator.cpp new file mode 100644 index 0000000..f9d4ef3 --- /dev/null +++ b/src/midi/integrator/AbstractMidiMessageIntegrator.cpp @@ -0,0 +1,81 @@ +/****************************************************************************** + * Copyright (c) 2024 CrSjimo * + * * + * This file is part of TALCS. * + * * + * TALCS is free software: you can redistribute it and/or modify it under the * + * terms of the GNU Lesser General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * + * more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with TALCS. If not, see . * + ******************************************************************************/ + +#include "AbstractMidiMessageIntegrator.h" +#include "AbstractMidiMessageIntegrator_p.h" + +#include + +#include + +namespace talcs { + AbstractMidiMessageIntegrator::AbstractMidiMessageIntegrator() : AbstractMidiMessageIntegrator(*new AbstractMidiMessageIntegratorPrivate) { + + } + + AbstractMidiMessageIntegrator::~AbstractMidiMessageIntegrator() { + Q_D(AbstractMidiMessageIntegrator); + AbstractMidiMessageIntegrator::close(); + if (d->takeOwnership) + delete d->stream; + } + + bool AbstractMidiMessageIntegrator::open(qint64 bufferSize, double sampleRate) { + Q_D(AbstractMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + if (d->stream && !d->stream->open(bufferSize, sampleRate)) + return false; + return AudioSource::open(bufferSize, sampleRate); + } + + void AbstractMidiMessageIntegrator::close() { + Q_D(AbstractMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + if (d->stream) + d->stream->close(); + AudioSource::close(); + } + + void AbstractMidiMessageIntegrator::setStream(AudioMidiStream *stream, bool takeOwnership) { + Q_D(AbstractMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + d->stream = stream; + d->takeOwnership = takeOwnership; + if (isOpen()) + d->stream->open(bufferSize(), sampleRate()); + } + + AudioMidiStream *AbstractMidiMessageIntegrator::stream() const { + Q_D(const AbstractMidiMessageIntegrator); + return d->stream; + } + + qint64 AbstractMidiMessageIntegrator::processReading(const AudioSourceReadData &readData) { + Q_D(AbstractMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + auto midiEvents = fetch(readData.length); + if (d->stream) + return d->stream->read(readData, midiEvents); + return readData.length; + } + + AbstractMidiMessageIntegrator::AbstractMidiMessageIntegrator(AbstractMidiMessageIntegratorPrivate &d) : AudioSource(d) { + + } +} // talcs \ No newline at end of file diff --git a/src/midi/MidiSineWaveSynthesizer.h b/src/midi/integrator/AbstractMidiMessageIntegrator.h similarity index 66% rename from src/midi/MidiSineWaveSynthesizer.h rename to src/midi/integrator/AbstractMidiMessageIntegrator.h index 1d51da4..32989bb 100644 --- a/src/midi/MidiSineWaveSynthesizer.h +++ b/src/midi/integrator/AbstractMidiMessageIntegrator.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -17,41 +17,38 @@ * along with TALCS. If not, see . * ******************************************************************************/ -#ifndef TALCS_MIDISINEWAVESYNTHESIZER_H -#define TALCS_MIDISINEWAVESYNTHESIZER_H +#ifndef TALCS_ABSTRACTMIDIMESSAGEINTEGRATOR_H +#define TALCS_ABSTRACTMIDIMESSAGEINTEGRATOR_H #include -#include +#include namespace talcs { - class MidiSineWaveSynthesizerPrivate; + class AudioMidiStream; - class TALCSMIDI_EXPORT MidiSineWaveSynthesizer : public AudioSource, public MidiInputDeviceCallback { + class AbstractMidiMessageIntegratorPrivate; + + class TALCSMIDI_EXPORT AbstractMidiMessageIntegrator : public AudioSource { + Q_DECLARE_PRIVATE(AbstractMidiMessageIntegrator) public: - MidiSineWaveSynthesizer(); + explicit AbstractMidiMessageIntegrator(); + ~AbstractMidiMessageIntegrator() override; bool open(qint64 bufferSize, double sampleRate) override; - void close() override; - ~MidiSineWaveSynthesizer() override; - - void deviceWillStartCallback(MidiInputDevice *device) override; - - void deviceStoppedCallback() override; - - void workCallback(const MidiMessage &message) override; - - void errorCallback(const QString &errorString) override; + void setStream(AudioMidiStream *stream, bool takeOwnership = false); + AudioMidiStream *stream() const; protected: qint64 processReading(const AudioSourceReadData &readData) override; - private: - QScopedPointer d; + virtual QList fetch(qint64 length) = 0; + + explicit AbstractMidiMessageIntegrator(AbstractMidiMessageIntegratorPrivate &d); }; } // talcs -#endif //TALCS_MIDISINEWAVESYNTHESIZER_H +#endif //TALCS_ABSTRACTMIDIMESSAGEINTEGRATOR_H diff --git a/src/midi/MidiInputDeviceCallback.h b/src/midi/integrator/AbstractMidiMessageIntegrator_p.h similarity index 71% rename from src/midi/MidiInputDeviceCallback.h rename to src/midi/integrator/AbstractMidiMessageIntegrator_p.h index b07e3e5..6af94e8 100644 --- a/src/midi/MidiInputDeviceCallback.h +++ b/src/midi/integrator/AbstractMidiMessageIntegrator_p.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -17,23 +17,24 @@ * along with TALCS. If not, see . * ******************************************************************************/ -#ifndef TALCS_MIDIINPUTDEVICECALLBACK_H -#define TALCS_MIDIINPUTDEVICECALLBACK_H -#include +#ifndef TALCS_ABSTRACTMIDIMESSAGEINTEGRATOR_P_H +#define TALCS_ABSTRACTMIDIMESSAGEINTEGRATOR_P_H -namespace talcs { +#include + +#include - class MidiInputDevice; +#include - class TALCSMIDI_EXPORT MidiInputDeviceCallback { +namespace talcs { + class AbstractMidiMessageIntegratorPrivate : public AudioSourcePrivate { + Q_DECLARE_PUBLIC(AbstractMidiMessageIntegrator) public: - virtual void deviceWillStartCallback(MidiInputDevice *device) = 0; - virtual void deviceStoppedCallback() = 0; - virtual void workCallback(const MidiMessage &message) = 0; - virtual void errorCallback(const QString &errorString) = 0; + QMutex mutex; + AudioMidiStream *stream = nullptr; + bool takeOwnership = false; }; +} -} // talcs - -#endif //TALCS_MIDIINPUTDEVICECALLBACK_H +#endif //TALCS_ABSTRACTMIDIMESSAGEINTEGRATOR_P_H diff --git a/src/midi/integrator/AudioMidiStream.cpp b/src/midi/integrator/AudioMidiStream.cpp new file mode 100644 index 0000000..4b141fe --- /dev/null +++ b/src/midi/integrator/AudioMidiStream.cpp @@ -0,0 +1,72 @@ +/****************************************************************************** + * Copyright (c) 2024 CrSjimo * + * * + * This file is part of TALCS. * + * * + * TALCS is free software: you can redistribute it and/or modify it under the * + * terms of the GNU Lesser General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * + * more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with TALCS. If not, see . * + ******************************************************************************/ + +#include "AudioMidiStream.h" +#include "AudioMidiStream_p.h" + +namespace talcs { + AudioMidiStream::AudioMidiStream() : AudioMidiStream(*new AudioMidiStreamPrivate) { + } + + AudioMidiStream::AudioMidiStream(AudioMidiStreamPrivate &d) : d_ptr(&d) { + d.q_ptr = this; + } + AudioMidiStream::~AudioMidiStream() = default; + + bool AudioMidiStream::open(qint64 bufferSize, double sampleRate) { + Q_D(AudioMidiStream); + QMutexLocker locker(&d->filterMutex); + if (d->filter.loadRelaxed() && !d->filter.loadRelaxed()->open(bufferSize, sampleRate)) { + return false; + } + return AudioStreamBase::open(bufferSize, sampleRate); + } + + void AudioMidiStream::close() { + Q_D(AudioMidiStream); + QMutexLocker locker(&d->filterMutex); + if (d->filter.loadRelaxed()) + d->filter.loadRelaxed()->close(); + AudioStreamBase::close(); + } + + qint64 AudioMidiStream::read(const AudioSourceReadData &readData, const QList &midiEvents) { + Q_D(AudioMidiStream); + qint64 l = processReading(readData, midiEvents); + if (!d->filter) return l; + QMutexLocker locker(&d->filterMutex); + if (d->filter.loadRelaxed()) { + d->filter.loadRelaxed()->read({readData.buffer, readData.startPos, l, readData.silentFlags}, midiEvents); + } + return l; + } + + void AudioMidiStream::setReadingFilter(AudioMidiStream *filter) { + Q_D(AudioMidiStream); + QMutexLocker locker(&d->filterMutex); + d->filter = filter; + if (isOpen()) + filter->open(bufferSize(), sampleRate()); + } + + AudioMidiStream *AudioMidiStream::readingFilter() const { + Q_D(const AudioMidiStream); + return d->filter; + } +} // talcs \ No newline at end of file diff --git a/src/midi/integrator/AudioMidiStream.h b/src/midi/integrator/AudioMidiStream.h new file mode 100644 index 0000000..293a9fc --- /dev/null +++ b/src/midi/integrator/AudioMidiStream.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Copyright (c) 2024 CrSjimo * + * * + * This file is part of TALCS. * + * * + * TALCS is free software: you can redistribute it and/or modify it under the * + * terms of the GNU Lesser General Public License as published by the Free * + * Software Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY * + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * + * more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with TALCS. If not, see . * + ******************************************************************************/ + +#ifndef TALCS_AUDIOMIDISTREAM_H +#define TALCS_AUDIOMIDISTREAM_H + +#include +#include + +namespace talcs { + + class AudioMidiStreamPrivate; + + class TALCSMIDI_EXPORT AudioMidiStream : public AudioStreamBase { + Q_DECLARE_PRIVATE(AudioMidiStream) + public: + explicit AudioMidiStream(); + + virtual ~AudioMidiStream(); + + bool open(qint64 bufferSize, double sampleRate) override; + + void close() override; + + qint64 read(const AudioSourceReadData &readData, const QList &midiEvents); + + void setReadingFilter(AudioMidiStream *filter); + + AudioMidiStream *readingFilter() const; + + protected: + explicit AudioMidiStream(AudioMidiStreamPrivate &d); + QScopedPointer d_ptr; + + virtual qint64 processReading(const AudioSourceReadData &readData, const QList &midiEvents) = 0; + + }; + +} // talcs + +#endif //TALCS_AUDIOMIDISTREAM_H diff --git a/src/midi/MidiInputDevice_p.h b/src/midi/integrator/AudioMidiStream_p.h similarity index 77% rename from src/midi/MidiInputDevice_p.h rename to src/midi/integrator/AudioMidiStream_p.h index b804152..2fbe40e 100644 --- a/src/midi/MidiInputDevice_p.h +++ b/src/midi/integrator/AudioMidiStream_p.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -17,20 +17,24 @@ * along with TALCS. If not, see . * ******************************************************************************/ -#ifndef TALCS_MIDIINPUTDEVICE_P_H -#define TALCS_MIDIINPUTDEVICE_P_H +#ifndef TALCS_AUDIOMIDISTREAM_P_H +#define TALCS_AUDIOMIDISTREAM_P_H -#include +#include -class RtMidiIn; +#include namespace talcs { - class MidiInputDevicePrivate { + + class AudioMidiStreamPrivate { + Q_DECLARE_PUBLIC(AudioMidiStream) public: - int portNumber; - QScopedPointer midi; - QList listeners; + AudioMidiStream *q_ptr; + + QMutex filterMutex; + QAtomicPointer filter = nullptr; }; + } -#endif //TALCS_MIDIINPUTDEVICE_P_H +#endif // TALCS_AUDIOMIDISTREAM_P_H diff --git a/src/midi/MidiInputDeviceCallback.cpp b/src/midi/integrator/IntegratedMidiMessage.h similarity index 81% rename from src/midi/MidiInputDeviceCallback.cpp rename to src/midi/integrator/IntegratedMidiMessage.h index 29d189a..9929f58 100644 --- a/src/midi/MidiInputDeviceCallback.cpp +++ b/src/midi/integrator/IntegratedMidiMessage.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2023 CrSjimo * + * Copyright (c) 2024 CrSjimo * * * * This file is part of TALCS. * * * @@ -17,7 +17,18 @@ * along with TALCS. If not, see . * ******************************************************************************/ -#include "MidiInputDeviceCallback.h" +#ifndef TALCS_INTEGRATEDMIDIMESSAGE_H +#define TALCS_INTEGRATEDMIDIMESSAGE_H + +#include namespace talcs { -} // talcs \ No newline at end of file + + struct IntegratedMidiMessage { + qint64 position; + MidiMessage message; + }; + +} // talcs + +#endif //TALCS_INTEGRATEDMIDIMESSAGE_H diff --git a/tests/InteractiveTests/CMakeLists.txt b/tests/InteractiveTests/CMakeLists.txt index 2226be0..4f8da54 100644 --- a/tests/InteractiveTests/CMakeLists.txt +++ b/tests/InteractiveTests/CMakeLists.txt @@ -26,4 +26,4 @@ add_subdirectory(AudioProcessorVisualization) add_subdirectory(AudioSourceReadingFilter) -add_subdirectory(SineWaveNoteSynthesizer) \ No newline at end of file +add_subdirectory(NoteSynthesizer) \ No newline at end of file diff --git a/tests/InteractiveTests/SineWaveNoteSynthesizer/CMakeLists.txt b/tests/InteractiveTests/NoteSynthesizer/CMakeLists.txt similarity index 78% rename from tests/InteractiveTests/SineWaveNoteSynthesizer/CMakeLists.txt rename to tests/InteractiveTests/NoteSynthesizer/CMakeLists.txt index 95cac2a..667049a 100644 --- a/tests/InteractiveTests/SineWaveNoteSynthesizer/CMakeLists.txt +++ b/tests/InteractiveTests/NoteSynthesizer/CMakeLists.txt @@ -1,4 +1,4 @@ -project(tst_talcs_SineWaveNoteSynthesizer) +project(tst_talcs_NoteSynthesizer) file(GLOB _src *.h *.cpp) diff --git a/tests/InteractiveTests/SineWaveNoteSynthesizer/main.cpp b/tests/InteractiveTests/NoteSynthesizer/main.cpp similarity index 91% rename from tests/InteractiveTests/SineWaveNoteSynthesizer/main.cpp rename to tests/InteractiveTests/NoteSynthesizer/main.cpp index 3120088..7eac80e 100644 --- a/tests/InteractiveTests/SineWaveNoteSynthesizer/main.cpp +++ b/tests/InteractiveTests/NoteSynthesizer/main.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -34,7 +34,7 @@ static inline double calcFreq(int key) { return 440.0 * std::pow(2.0, (key - 69) / 12.0); } -class Detector : public SineWaveNoteSynthesizerDetector { +class Detector : public NoteSynthesizerDetector { public: void detectInterval(qint64 intervalLength) override { currentPos = pos / 12000 * 12000; @@ -46,7 +46,7 @@ class Detector : public SineWaveNoteSynthesizerDetector { posDelta = intervalLength; } - SineWaveNoteSynthesizerDetectorMessage nextMessage() override { + NoteSynthesizerDetectorMessage nextMessage() override { if (!retQueue.isEmpty()) { return retQueue.takeFirst(); } @@ -55,7 +55,7 @@ class Detector : public SineWaveNoteSynthesizerDetector { posDelta = 0; return {-1, false}; } - SineWaveNoteSynthesizerDetectorMessage ret = {currentPos - pos, 0, 0.5, true}; + NoteSynthesizerDetectorMessage ret = {currentPos - pos, 0, 0.5, true}; switch (currentPos % (12000 * 8)) { case 12000 * 0: ret.frequency = calcFreq(60); @@ -104,7 +104,7 @@ class Detector : public SineWaveNoteSynthesizerDetector { return ret; } - QList retQueue; + QList retQueue; private: qint64 pos = 0; @@ -125,7 +125,10 @@ int main(int argc, char **argv) { dev->open(dev->preferredBufferSize(), 48000); Detector detector; - SineWaveNoteSynthesizer src; + NoteSynthesizer src; + src.setAttackRate(std::pow(0.99, 20000.0 / 48000.0)); + src.setReleaseRate(std::pow(0.99, 20000.0 / 48000.0)); + src.setGenerator(NoteSynthesizer::Square); src.setDetector(&detector); AudioSourcePlayback playback(&src); dev->start(&playback); diff --git a/tests/InteractiveTests/midi/main.cpp b/tests/InteractiveTests/midi/main.cpp index 54e965d..4b2defa 100644 --- a/tests/InteractiveTests/midi/main.cpp +++ b/tests/InteractiveTests/midi/main.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -41,17 +40,17 @@ int main(int argc, char **argv) { qDebug() << MidiInputDevice::devices(); MidiInputDevice dev(1); - auto mgr = AudioDriverManager::createBuiltInDriverManager(); - auto drv = mgr->driver(mgr->drivers()[0]); - drv->initialize(); - auto audioDev = drv->defaultDevice().isEmpty() ? drv->createDevice(drv->devices()[0]) : drv->createDevice(drv->defaultDevice()); +// auto mgr = AudioDriverManager::createBuiltInDriverManager(); +// auto drv = mgr->driver(mgr->drivers()[0]); +// drv->initialize(); +// auto audioDev = drv->defaultDevice().isEmpty() ? drv->createDevice(drv->devices()[0]) : drv->createDevice(drv->defaultDevice()); - auto midiSynth = new MidiSineWaveSynthesizer; - auto playback = new AudioSourcePlayback(midiSynth); - dev.addListener(midiSynth); +// auto midiSynth = new MidiSineWaveSynthesizer; +// auto playback = new AudioSourcePlayback(midiSynth); +// dev.addListener(midiSynth); - audioDev->open(audioDev->preferredBufferSize(), audioDev->preferredSampleRate()); - audioDev->start(playback); +// audioDev->open(audioDev->preferredBufferSize(), audioDev->preferredSampleRate()); +// audioDev->start(playback); dev.open(); return a.exec(); } \ No newline at end of file