#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(); }