first commit
This commit is contained in:
16
bytebeat.pro
Normal file
16
bytebeat.pro
Normal file
@ -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
|
190
main.cpp
Normal file
190
main.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#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();
|
||||
}
|
Reference in New Issue
Block a user