From d5932b950778cd6d6aedcec1207a27e2b7aa0828 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Sun, 22 Jun 2025 21:55:21 +0200 Subject: [PATCH] first commit --- bytebeat.pro | 16 +++++ main.cpp | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 bytebeat.pro create mode 100644 main.cpp diff --git a/bytebeat.pro b/bytebeat.pro new file mode 100644 index 0000000..0dd58b5 --- /dev/null +++ b/bytebeat.pro @@ -0,0 +1,16 @@ +QT = core multimedia + +CONFIG += c++11 console +CONFIG -= app_bundle + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..dfa25c6 --- /dev/null +++ b/main.cpp @@ -0,0 +1,190 @@ +#include +#include +#include +/** Dont forget to set QT += core multimedia **/ +#include +#include +#include + +/** + * @brief Interface class for all byte beat musicals + */ +template +class MusicDevice : public QIODevice +{ +public: + explicit MusicDevice(QObject *parent = Q_NULLPTR) : QIODevice(parent) {} + virtual ~MusicDevice() {} + + virtual SAMPLE_TYPE getSample() = 0; + virtual const QAudioFormat& getFormat() const + { + static QAudioFormat format; + format.setSampleRate(SAMPLE_RATE); + format.setChannelCount(STEREO ? 2 : 1); + format.setSampleSize(sizeof(SAMPLE_TYPE) * 8); + format.setCodec("audio/pcm"); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setSampleType(QAudioFormat::UnSignedInt); //TODO: make this depend on SAMPLE_TYPE + return format; + } + + // qt specific implementation + bool open(OpenMode mode) + { + auto success = mode == QIODevice::ReadOnly; + if(success) + setOpenMode(mode); + else + qWarning() << "unsupported open mode" << mode; + return success; + } + + void close() + { + setOpenMode(NotOpen); + } + + bool isSequential() const + { + return true; + } + +protected: + qint64 readData(char* data, qint64 maxSize) + { + for(qint64 i = 0; i < maxSize; i++) + data[i] = getSample(); + return maxSize; + } + + qint64 writeData(const char* data, qint64 maxSize) + { + Q_UNUSED(data) + Q_UNUSED(maxSize) + + qWarning() << "read only device!"; + + return -1; + } +}; + +/** + * @brief Bitshift variations by Rob Miles + * https://www.youtube.com/watch?v=MqZgoNRERY8&t=1s + * http://txti.es/bitshiftvariationsincminor + */ +class BitshiftVariations : public MusicDevice +{ +public: + explicit BitshiftVariations(QObject *parent = Q_NULLPTR) : MusicDevice(parent) {} + virtual ~BitshiftVariations() {} + + quint8 getSample() Q_DECL_OVERRIDE + { + int voice0 = g(i, 1, n = i >> 14, 12); + int voice1 = g(i, s = i >> 17, n ^ i >> 13, 10); + int voice2 = g(i, s / 3, n + ((i >> 11) % 3), 10); + int voice3 = g(i, s / 5, 8 + n - ((i >> 10) % 3), 9); + i++; + + return voice0 + voice1 + voice2 + voice3; + } + +private: + static int g(int i, int x, int t, int o) + { + return ((3 & x & (i * ((3 & i >> 16 ? "BY}6YB6%" : "Qj}6jQ6%")[t % 8] + 51) >> o)) << 4); + } + + int i, n, s; +}; + +/** + * @brief Funky beat found in some forum + */ +class FunkyBeat : public MusicDevice +{ +public: + explicit FunkyBeat(QObject *parent = Q_NULLPTR) : MusicDevice(parent), a(0), f(true) {} + virtual ~FunkyBeat() {} + + quint8 getSample() Q_DECL_OVERRIDE + { + if(f) + { + b = 99; + c = 99; + d = 99; + + while(true) + { + if("+%7%+%7%5%4%2%457%0%0%754%2%+%%%5%542%457%0%0%042%2#+%!#0%+%$%%%"[a] > b) + d = d * 89 / 84; + + if(b-- == 0) + break; + + if("057+5420"[a / 8] > b) + c = c * 89 / 84; + } + + s = 999 + 99 * (a & 2); + + f = false; + } + + quint8 sample = + s * ( + (776 - d ? + s * d & 32767 : + b + ) + + (a & 2 ? + s * c / 2 & 32767 : + b + ) + ) / 299999; + + if(s-- == 0) + { + f = true; + a++; + a &= 63; + } + + return sample; + } + +private: + int a; + int b; + int c; + int d; + int s; + bool f; +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + //MusicDevice *source = new BitshiftVariations(&app); + MusicDevice *source = new FunkyBeat(&app); + + { + QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); + if (!info.isFormatSupported(source->getFormat())) + { + qFatal("Your soundcard does not support the needed output format!"); + return -1; + } + } + + QAudioOutput *audioOutput = new QAudioOutput(source->getFormat(), &app); + + source->open(QIODevice::ReadOnly); + audioOutput->start(source); + + return app.exec(); +}