Created
October 14, 2017 12:59
-
-
Save 0xFEEDC0DE64/daaaaba24fa05232b2a6ace8e0a25232 to your computer and use it in GitHub Desktop.
Byte beat collection wrapped into general interface and Qt player (windows & linux compatible!)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QCoreApplication> | |
#include <QIODevice> | |
#include <QDebug> | |
/** Dont forget to set QT += core multimedia **/ | |
#include <QtMultimedia/QAudioFormat> | |
#include <QtMultimedia/QAudioDeviceInfo> | |
#include <QtMultimedia/QAudioOutput> | |
/** | |
* @brief Interface class for all byte beat musicals | |
*/ | |
template<typename SAMPLE_TYPE, int SAMPLE_RATE, bool STEREO> | |
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<quint8, 8000, false> | |
{ | |
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<quint8, 8000, false> | |
{ | |
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<quint8, 8000, false> *source = new BitshiftVariations(&app); | |
MusicDevice<quint8, 8000, false> *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(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment