aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorVitaly Novichkov <admin@wohlnet.ru>2019-07-01 05:01:55 +0300
committerVitaly Novichkov <admin@wohlnet.ru>2019-07-01 05:01:55 +0300
commit81f905ea76f0efb6ea35331bd1fe476f14f804de (patch)
tree8146611e945a5080db9e7f6fc1805cc77565204b /utils
parentd02cf717c2da0344b37db1ffb864d312713f3208 (diff)
downloadlibADLMIDI-81f905ea76f0efb6ea35331bd1fe476f14f804de.tar.gz
libADLMIDI-81f905ea76f0efb6ea35331bd1fe476f14f804de.tar.bz2
libADLMIDI-81f905ea76f0efb6ea35331bd1fe476f14f804de.zip
First working of new database
// not so stable, needs a polishing, however, multibank from embedded 72'th bank (DMXOPL3) works!
Diffstat (limited to 'utils')
-rw-r--r--utils/gen_adldata/CMakeLists.txt5
-rw-r--r--utils/gen_adldata/gen_adldata.cc3
-rw-r--r--utils/gen_adldata/measurer.cpp155
-rw-r--r--utils/gen_adldata/measurer.h6
-rw-r--r--utils/gen_adldata/progs_cache.h7
-rwxr-xr-xutils/midiplay/wave_writer.c214
-rwxr-xr-xutils/midiplay/wave_writer.h20
7 files changed, 266 insertions, 144 deletions
diff --git a/utils/gen_adldata/CMakeLists.txt b/utils/gen_adldata/CMakeLists.txt
index e214534..46c2525 100644
--- a/utils/gen_adldata/CMakeLists.txt
+++ b/utils/gen_adldata/CMakeLists.txt
@@ -19,6 +19,11 @@ list(APPEND GEN_ADLDATA_SRC
ini/ini_processing.cpp
)
+#add_definitions(-DGEN_ADLDATA_DEEP_DEBUG)
+#list(APPEND GEN_ADLDATA_SRC
+# ../midiplay/wave_writer.c
+#)
+
if(USE_DOSBOX_EMULATOR)
set(HAS_EMULATOR TRUE)
list(APPEND GEN_ADLDATA_SRC
diff --git a/utils/gen_adldata/gen_adldata.cc b/utils/gen_adldata/gen_adldata.cc
index f0c1265..2b94ab6 100644
--- a/utils/gen_adldata/gen_adldata.cc
+++ b/utils/gen_adldata/gen_adldata.cc
@@ -341,6 +341,7 @@ int main(int argc, char**argv)
std::fprintf(outFile, "{\n");
MeasureThreaded measureCounter;
+#ifndef GEN_ADLDATA_DEEP_DEBUG // Skip slowest place to work with a debug
{
std::printf("Beginning to generate measures data... (hardware concurrency of %d)\n", std::thread::hardware_concurrency());
std::fflush(stdout);
@@ -358,6 +359,7 @@ int main(int argc, char**argv)
measureCounter.waitAll();
measureCounter.SaveCache("fm_banks/adldata-cache.dat");
}
+#endif
std::printf("Writing generated measure data...\n");
std::fflush(stdout);
@@ -566,6 +568,7 @@ int main(int argc, char**argv)
std::fflush(stdout);
for(size_t b = 0; b < db.instruments.size(); ++b)
{
+ assert(db.instruments[b].instId == b);
measureCounter.run(db, db.instruments[b]);
}
std::fflush(stdout);
diff --git a/utils/gen_adldata/measurer.cpp b/utils/gen_adldata/measurer.cpp
index 1b49011..23e3883 100644
--- a/utils/gen_adldata/measurer.cpp
+++ b/utils/gen_adldata/measurer.cpp
@@ -2,6 +2,10 @@
#include "file_formats/common.h"
#include <cmath>
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+#include "../midiplay/wave_writer.h"
+#endif
+
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
@@ -58,6 +62,14 @@ static const uint16_t g_operatorsMap[(NUM_OF_CHANNELS + NUM_OF_RM_CHANNELS) * 2]
0x011, 0xFFF // operator 13
};
+//! Channel map to regoster offsets
+static const uint16_t g_channelsMap[NUM_OF_CHANNELS] =
+{
+ 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, // 0..8
+ 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, // 9..17 (secondary set)
+ 0x006, 0x007, 0x008, 0x008, 0x008 // <- hw percussions, hihats and cymbals using tom-tom's channel as pitch source
+};
+
template <class T>
class AudioHistory
@@ -130,8 +142,11 @@ struct TinySynth
{
OPLChipBase *m_chip;
unsigned m_notesNum;
- int m_notenum;
- int8_t m_fineTune;
+ unsigned m_actualNotesNum;
+ bool m_isReal4op;
+ bool m_isPseudo4op;
+ int m_playNoteNum;
+ int8_t m_voice1Detune;
int16_t m_noteOffsets[2];
unsigned m_x[2];
@@ -146,6 +161,8 @@ struct TinySynth
m_chip->setRate(g_outputRate);
+ for(size_t a = 0; a < 18; ++a)
+ m_chip->writeReg(0xB0 + g_channelsMap[a], 0x00);
for(unsigned a = 0; a < 18; a += 2)
m_chip->writeReg((uint16_t)initdata[a], (uint8_t)initdata[a + 1]);
}
@@ -173,20 +190,19 @@ struct TinySynth
}
std::memset(m_x, 0, sizeof(m_x));
- m_notenum = in.notenum >= 128 ? (in.notenum - 128) : in.notenum;
- if(m_notenum == 0)
- m_notenum = 25;
+ m_playNoteNum = in.notenum >= 128 ? (in.notenum - 128) : in.notenum;
+ m_isReal4op = in.real4op && !in.pseudo4op;
+ m_isPseudo4op = in.pseudo4op;
+ if(m_playNoteNum == 0)
+ m_playNoteNum = 25;
m_notesNum = in.insno1 == in.insno2 ? 1 : 2;
- m_fineTune = 0;
+ m_actualNotesNum = (m_isReal4op ? 1 : m_notesNum);
+ m_voice1Detune = 0;
m_noteOffsets[0] = rawData[0].finetune;
m_noteOffsets[1] = rawData[1].finetune;
if(in.pseudo4op)
- m_fineTune = in.voice2_fine_tune;
- if(in.real4op)
- {
- m_chip->writeReg(0x105, 1);
- m_chip->writeReg(0x104, 0xFF);
- }
+ m_voice1Detune = in.voice2_fine_tune;
+ m_chip->writeReg(0x104, in.real4op ? (1 << 6) - 1 : 0x00);
//For cleaner measurement, disable tremolo and vibrato
rawData[0].data[0] &= 0x3F;
@@ -206,9 +222,8 @@ struct TinySynth
void setInstrument(const BanksDump &db, const BanksDump::InstrumentEntry &ins)
{
- // TODO: Implement this function correctly!
- bool is4ops = ((ins.instFlags & BanksDump::InstrumentEntry::WOPL_Ins_4op) != 0);
bool isPseudo4ops = ((ins.instFlags & BanksDump::InstrumentEntry::WOPL_Ins_Pseudo4op) != 0);
+ bool is4ops = ((ins.instFlags & BanksDump::InstrumentEntry::WOPL_Ins_4op) != 0) && !isPseudo4ops;
size_t opsNum = (is4ops || isPseudo4ops) ? 4 : 2;
BanksDump::Operator ops[4];
assert(ins.ops[0] >= 0);
@@ -224,24 +239,25 @@ struct TinySynth
}
std::memset(m_x, 0, sizeof(m_x));
- m_notenum = ins.percussionKeyNumber >= 128 ? (ins.percussionKeyNumber - 128) : ins.percussionKeyNumber;
- if(m_notenum == 0)
- m_notenum = 25;
+ m_playNoteNum = ins.percussionKeyNumber >= 128 ? (ins.percussionKeyNumber - 128) : ins.percussionKeyNumber;
+ m_isReal4op = is4ops;
+ m_isPseudo4op = isPseudo4ops;
+ if(m_playNoteNum == 0)
+ m_playNoteNum = 60;
m_notesNum = opsNum / 2;
- m_fineTune = 0;
+ m_actualNotesNum = (m_isReal4op ? 1 : m_notesNum);
+ m_voice1Detune = 0;
m_noteOffsets[0] = ins.noteOffset1;
m_noteOffsets[1] = ins.noteOffset2;
if(isPseudo4ops)
- m_fineTune = ins.secondVoiceDetune;
- if(is4ops)
- {
- m_chip->writeReg(0x105, 1);
- m_chip->writeReg(0x104, 0xFF);
- }
+ m_voice1Detune = ins.secondVoiceDetune;
+ m_chip->writeReg(0x104, is4ops ? (1 << 6) - 1 : 0x00);
//For cleaner measurement, disable tremolo and vibrato
- ops[0].d_E862 &= 0xFFFF3F3F;
- ops[1].d_E862 &= 0xFFFF3F3F;
+ ops[0].d_E862 &= 0xFFFFFF3F;
+ ops[1].d_E862 &= 0xFFFFFF3F;
+ ops[2].d_E862 &= 0xFFFFFF3F;
+ ops[3].d_E862 &= 0xFFFFFF3F;
// rawData[0].data[0] &= 0x3F;
// rawData[0].data[1] &= 0x3F;
// rawData[1].data[0] &= 0x3F;
@@ -252,16 +268,19 @@ struct TinySynth
static const uint8_t data[4] = {0x20, 0x60, 0x80, 0xE0};
uint16_t o1 = g_operatorsMap[0];
uint16_t o2 = g_operatorsMap[1];
- unsigned x = ops[0].d_E862, y = ops[1].d_E862;
+ size_t opOffset = (n * 2);
+ uint_fast32_t x1 = ops[opOffset + 0].d_E862, y1 = ops[opOffset + 1].d_E862;
+ uint_fast8_t x2 = ops[opOffset + 0].d_40, y2 = ops[opOffset + 1].d_40;
+ uint_fast8_t fbConn = (ins.fbConn >> (n * 8)) & 0xFF;
- for(size_t a = 0; a < 4; ++a, x >>= 8, y >>= 8)
+ for(size_t a = 0; a < 4; ++a, x1 >>= 8, y1 >>= 8)
{
- if(o1 != 0xFFF)
- m_chip->writeReg(data[a] + o1, x & 0xFF);
- if(o2 != 0xFFF)
- m_chip->writeReg(data[a] + o2, y & 0xFF);
+ m_chip->writeReg(data[a] + o1, x1 & 0xFF);
+ m_chip->writeReg(data[a] + o2, y1 & 0xFF);
}
- m_chip->writeReg(0xC0 + n * 8, (ins.fbConn >> n * 8) & 0xFF);
+ m_chip->writeReg(0xC0 + (n * 8), fbConn | 0x30);
+ m_chip->writeReg(0x40 + o1, x2 & 0xFF);
+ m_chip->writeReg(0x40 + o2, y2 & 0xFF);
}
// for(unsigned n = 0; n < m_notesNum; ++n)
@@ -269,27 +288,25 @@ struct TinySynth
// static const unsigned char patchdata[11] =
// {0x20, 0x23, 0x60, 0x63, 0x80, 0x83, 0xE0, 0xE3, 0x40, 0x43, 0xC0};
// for(unsigned a = 0; a < 10; ++a)
-// {
// m_chip->writeReg(patchdata[a] + n * 8, rawData[n].data[a]);
-// }
-// m_chip->writeReg(patchdata[10] + n * 8, (ins.fbConn >> n * 8) & 0xFF);
+// m_chip->writeReg(patchdata[10] + n * 8, rawData[n].data[10] | 0x30);
// }
}
void noteOn()
{
std::memset(m_x, 0, sizeof(m_x));
- for(unsigned n = 0; n < m_notesNum; ++n)
+ for(unsigned n = 0; n < m_actualNotesNum; ++n)
{
- double hertz = 172.00093 * std::exp(0.057762265 * (m_notenum + m_noteOffsets[n]));
+ double hertz = 172.00093 * std::exp(0.057762265 * (m_playNoteNum + m_noteOffsets[n]));
if(hertz > 131071)
{
std::fprintf(stdout, "%s:%d:0: warning: Why does note %d + note-offset %d produce hertz %g?\n", __FILE__, __LINE__,
- m_notenum, m_noteOffsets[n], hertz);
+ m_playNoteNum, m_noteOffsets[n], hertz);
std::fflush(stdout);
hertz = 131071;
}
- m_x[n] = 0x2000;
+ m_x[n] = 0x2000u;
while(hertz >= 1023.5)
{
hertz /= 2.0; // Calculate octave
@@ -298,16 +315,16 @@ struct TinySynth
m_x[n] += (unsigned int)(hertz + 0.5);
// Keyon the note
- m_chip->writeReg(0xA0 + n * 3, m_x[n] & 0xFF);
- m_chip->writeReg(0xB0 + n * 3, m_x[n] >> 8);
+ m_chip->writeReg(0xA0 + (n * 3), m_x[n] & 0xFF);
+ m_chip->writeReg(0xB0 + (n * 3), (m_x[n] >> 8) & 0xFF);
}
}
void noteOff()
{
// Keyoff the note
- for(unsigned n = 0; n < m_notesNum; ++n)
- m_chip->writeReg(0xB0 + n * 3, (m_x[n] >> 8) & 0xDF);
+ for(unsigned n = 0; n < m_actualNotesNum; ++n)
+ m_chip->writeReg(0xB0 + (n * 3), (m_x[n] >> 8) & 0xDF);
}
void generate(int16_t *output, size_t frames)
@@ -528,6 +545,19 @@ DurationInfo MeasureDurations(BanksDump &db, const BanksDump::InstrumentEntry &i
synth.setInstrument(db, ins);
synth.noteOn();
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+ /*****************DEBUG******************/
+ char waveFileOut[80] = "";
+ std::snprintf(waveFileOut, 80, "fm_banks/_deep_debug/%04lu_%s_%u_an_%u_no.wav",
+ ins.instId, synth.m_isPseudo4op ? "pseudo4op" :
+ synth.m_isReal4op ? "4op" : "2op",
+ synth.m_actualNotesNum,
+ synth.m_notesNum);
+ void *waveCtx = ctx_wave_open(g_outputRate, waveFileOut);
+ ctx_wave_enable_stereo(waveCtx);
+ /*****************DEBUG******************/
+#endif
+
/* For capturing */
const unsigned max_silent = 6;
const unsigned max_on = 40;
@@ -566,6 +596,11 @@ DurationInfo MeasureDurations(BanksDump &db, const BanksDump::InstrumentEntry &i
size_t blocksize = samples_per_interval - i;
blocksize = (blocksize < audioBufferLength) ? blocksize : audioBufferLength;
synth.generate(audioBuffer, blocksize);
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+ /***************DEBUG******************/
+ ctx_wave_write(waveCtx, audioBuffer, blocksize * 2);
+ /***************DEBUG******************/
+#endif
for (unsigned j = 0; j < blocksize; ++j)
{
int16_t s = audioBuffer[2 * j];
@@ -697,11 +732,26 @@ DurationInfo MeasureDurations(BanksDump &db, const BanksDump::InstrumentEntry &i
db.instruments[ins.instId].delay_on_ms = result.ms_sound_kon;
db.instruments[ins.instId].delay_off_ms = result.ms_sound_koff;
+ if(result.nosound)
+ db.instruments[ins.instId].instFlags |= BanksDump::InstrumentEntry::WOPL_Ins_IsBlank;
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+ /***************DEBUG******************/
+ ctx_wave_close(waveCtx);
+ /***************DEBUG******************/
+#endif
return result;
}
+MeasureThreaded::MeasureThreaded() :
+ m_semaphore(int(std::thread::hardware_concurrency()) * 2),
+ m_done(0),
+ m_cache_matches(0)
+{
+ DosBoxOPL3::globalPreInit();
+}
+
void MeasureThreaded::LoadCache(const char *fileName)
{
m_durationInfo.clear();
@@ -983,7 +1033,7 @@ void MeasureThreaded::LoadCacheX(const char *fileName)
OperatorsKey k;
DurationInfo v;
- uint8_t data_k[4];
+ uint8_t data_k[5];
for(auto &kv : k)
{
@@ -1000,8 +1050,8 @@ void MeasureThreaded::LoadCacheX(const char *fileName)
kv = static_cast<int_fast32_t>(toSint32LE(data));
}
- auto ret = std::fread(data_k, 1, 4, in);
- if(ret != 4)
+ auto ret = std::fread(data_k, 1, 5, in);
+ if(ret != 5)
{
std::fclose(in);
std::printf("Failed to load CacheX: unexpected end of file.\n"
@@ -1012,6 +1062,7 @@ void MeasureThreaded::LoadCacheX(const char *fileName)
v.ms_sound_kon = static_cast<int_fast64_t>(toUint16LE(data_k + 0));
v.ms_sound_koff = static_cast<int_fast64_t>(toUint16LE(data_k + 2));
+ v.nosound = (data_k[4] == 0x01);
m_durationInfoX.insert({k, v});
itemsCount--;
@@ -1043,12 +1094,13 @@ void MeasureThreaded::SaveCacheX(const char *fileName)
const OperatorsKey &k = it->first;
const DurationInfo &v = it->second;
- uint8_t data_k[4] =
+ uint8_t data_k[5] =
{
static_cast<uint8_t>((v.ms_sound_kon >> 0) & 0xFF),
static_cast<uint8_t>((v.ms_sound_kon >> 8) & 0xFF),
static_cast<uint8_t>((v.ms_sound_koff >> 0) & 0xFF),
- static_cast<uint8_t>((v.ms_sound_koff >> 8) & 0xFF)
+ static_cast<uint8_t>((v.ms_sound_koff >> 8) & 0xFF),
+ static_cast<uint8_t>(v.nosound ? 0x01 : 0x00)
};
for(auto &kv : k)
@@ -1062,7 +1114,7 @@ void MeasureThreaded::SaveCacheX(const char *fileName)
};
std::fwrite(data, 1, 4, out);
}
- std::fwrite(data_k, 1, 4, out);
+ std::fwrite(data_k, 1, 5, out);
}
std::fclose(out);
}
@@ -1178,6 +1230,7 @@ void MeasureThreaded::destData::callback(void *myself)
destData *s = reinterpret_cast<destData *>(myself);
DurationInfo info;
DosBoxOPL3 dosbox;
+ // NukedOPL3 dosbox;
if(s->bd)
{
@@ -1192,6 +1245,8 @@ void MeasureThreaded::destData::callback(void *myself)
const DurationInfo &di = cachedEntry->second;
s->bd_ins->delay_on_ms = di.ms_sound_kon;
s->bd_ins->delay_off_ms = di.ms_sound_koff;
+ if(di.nosound)
+ s->bd_ins->instFlags |= BanksDump::InstrumentEntry::WOPL_Ins_IsBlank;
s->myself->m_cache_matches++;
goto endWork;
}
diff --git a/utils/gen_adldata/measurer.h b/utils/gen_adldata/measurer.h
index ed7810a..d2b8a76 100644
--- a/utils/gen_adldata/measurer.h
+++ b/utils/gen_adldata/measurer.h
@@ -59,11 +59,7 @@ struct MeasureThreaded
typedef std::map<ins, DurationInfo> DurationInfoCache;
typedef std::map<OperatorsKey, DurationInfo> DurationInfoCacheX;
- MeasureThreaded() :
- m_semaphore(int(std::thread::hardware_concurrency()) * 2),
- m_done(0),
- m_cache_matches(0)
- {}
+ MeasureThreaded();
Semaphore m_semaphore;
std::mutex m_durationInfo_mx;
diff --git a/utils/gen_adldata/progs_cache.h b/utils/gen_adldata/progs_cache.h
index 09f75f6..34e42a3 100644
--- a/utils/gen_adldata/progs_cache.h
+++ b/utils/gen_adldata/progs_cache.h
@@ -335,6 +335,13 @@ struct BanksDump
uint_fast32_t opId = 0;
uint_fast32_t d_E862 = 0;
uint_fast32_t d_40 = 0;
+ explicit Operator() {}
+ Operator(const Operator &o)
+ {
+ opId = o.opId;
+ d_E862 = o.d_E862;
+ d_40 = o.d_40;
+ }
bool operator==(const Operator &o)
{
return ((d_E862 == o.d_E862) && (d_40 == o.d_40));
diff --git a/utils/midiplay/wave_writer.c b/utils/midiplay/wave_writer.c
index e8ee10c..bdee5d7 100755
--- a/utils/midiplay/wave_writer.c
+++ b/utils/midiplay/wave_writer.c
@@ -26,145 +26,195 @@ enum { header_size = 0x2C };
typedef short sample_t;
-static unsigned char* buf;
-static FILE* file;
-static long sample_count_;
-static long sample_rate_;
-static long buf_pos;
-static int chan_count;
-
-static void exit_with_error( const char* str )
+struct Context
{
- fprintf(stderr, "WAVE Writer Error: %s\n", str );
+ unsigned char *m_buf;
+ FILE *m_file;
+ long m_sample_count;
+ long m_sample_rate;
+ long m_buf_pos;
+ int m_chan_count;
+};
+
+static struct Context *g_wwContext = NULL;
+
+static void exit_with_error(const char *str)
+{
+ fprintf(stderr, "WAVE Writer Error: %s\n", str);
fflush(stderr);
}
-int wave_open( long sample_rate, const char* filename )
+int wave_open(long sample_rate, const char *filename)
+{
+ g_wwContext = ctx_wave_open(sample_rate, filename);
+ return g_wwContext ? 0 : -1;
+}
+
+void wave_enable_stereo(void)
+{
+ ctx_wave_enable_stereo(g_wwContext);
+}
+
+void wave_write(short const *in, long remain)
+{
+ ctx_wave_write(g_wwContext, in, remain);
+}
+
+long wave_sample_count(void)
+{
+ return ctx_wave_sample_count(g_wwContext);
+}
+
+void wave_close(void)
{
- sample_count_ = 0;
- sample_rate_ = sample_rate;
- buf_pos = header_size;
- chan_count = 1;
+ ctx_wave_close(g_wwContext);
+}
+
+
+
+static void set_le32(void *p, unsigned long n)
+{
+ ((unsigned char *) p) [0] = (unsigned char) n & (0xFF);
+ ((unsigned char *) p) [1] = (unsigned char)(n >> 8) & (0xFF);
+ ((unsigned char *) p) [2] = (unsigned char)(n >> 16) & (0xFF);
+ ((unsigned char *) p) [3] = (unsigned char)(n >> 24) & (0xFF);
+}
- buf = (unsigned char*) malloc( buf_size * sizeof *buf );
- if ( !buf )
+void *ctx_wave_open(long sample_rate, const char *filename)
+{
+ struct Context *ctx = (struct Context*)malloc(sizeof(struct Context));
+ if(!ctx)
{
- exit_with_error( "Out of memory" );
- return -1;
+ exit_with_error("Out of memory");
+ return NULL;
+ }
+
+ ctx->m_sample_count = 0;
+ ctx->m_sample_rate = sample_rate;
+ ctx->m_buf_pos = header_size;
+ ctx->m_chan_count = 1;
+
+ ctx->m_buf = (unsigned char *) malloc(buf_size);
+ if(!ctx->m_buf)
+ {
+ exit_with_error("Out of memory");
+ free(ctx);
+ return NULL;
}
#if !defined(_WIN32) || defined(__WATCOMC__)
- file = fopen( filename, "wb" );
+ ctx->m_file = fopen(filename, "wb");
#else
wchar_t widePath[MAX_PATH];
int size = MultiByteToWideChar(CP_UTF8, 0, filename, strlen(filename), widePath, MAX_PATH);
widePath[size] = '\0';
- file = _wfopen( widePath, L"wb" );
+ ctx->m_file = _wfopen(widePath, L"wb");
#endif
- if (!file)
+ if(!ctx->m_file)
{
- exit_with_error( "Couldn't open WAVE file for writing" );
- return -1;
+ exit_with_error("Couldn't open WAVE file for writing");
+ free(ctx);
+ return NULL;
}
- setvbuf( file, 0, _IOFBF, 32 * 1024L );
- return 0;
+ setvbuf(ctx->m_file, 0, _IOFBF, 32 * 1024L);
+ return ctx;
}
-void wave_enable_stereo( void )
+void ctx_wave_enable_stereo(void *ctx)
{
- chan_count = 2;
+ struct Context *wWriter = (struct Context *)ctx;
+ wWriter->m_chan_count = 2;
}
-static void flush_()
+
+static void flush_(struct Context *ctx)
{
- if ( buf_pos && !fwrite( buf, (size_t)buf_pos, 1, file ) )
- exit_with_error( "Couldn't write WAVE data" );
- buf_pos = 0;
+ if(ctx->m_buf_pos && !fwrite(ctx->m_buf, (size_t)ctx->m_buf_pos, 1, ctx->m_file))
+ exit_with_error("Couldn't write WAVE data");
+ ctx->m_buf_pos = 0;
}
-void wave_write( short const* in, long remain )
+void ctx_wave_write(void *ctx, const short *in, long remain)
{
- sample_count_ += remain;
- while ( remain )
+ struct Context *wWriter = (struct Context *)ctx;
+ wWriter->m_sample_count += remain;
+ while(remain)
{
- if ( buf_pos >= buf_size )
- flush_();
-
+ if(wWriter->m_buf_pos >= buf_size)
+ flush_(wWriter);
{
- unsigned char* p = &buf [buf_pos];
- long n = (buf_size - (unsigned long)buf_pos) / sizeof (sample_t);
- if ( n > remain )
+ unsigned char *p = &wWriter->m_buf [wWriter->m_buf_pos];
+ long n = (buf_size - (unsigned long)wWriter->m_buf_pos) / sizeof(sample_t);
+ if(n > remain)
n = remain;
remain -= n;
/* convert to LSB first format */
- while ( n-- )
+ while(n--)
{
int s = *in++;
*p++ = (unsigned char) s & (0x00FF);
- *p++ = (unsigned char) (s >> 8) & (0x00FF);
+ *p++ = (unsigned char)(s >> 8) & (0x00FF);
}
- buf_pos = p - buf;
- assert( buf_pos <= buf_size );
+ wWriter->m_buf_pos = p - wWriter->m_buf;
+ assert(wWriter->m_buf_pos <= buf_size);
}
}
}
-long wave_sample_count( void )
+long ctx_wave_sample_count(void *ctx)
{
- return sample_count_;
+ struct Context *wWriter = (struct Context *)ctx;
+ return wWriter->m_sample_count;
}
-static void set_le32( void* p, unsigned long n )
+void ctx_wave_close(void *ctx)
{
- ((unsigned char*) p) [0] = (unsigned char) n & (0xFF);
- ((unsigned char*) p) [1] = (unsigned char) (n >> 8) & (0xFF);
- ((unsigned char*) p) [2] = (unsigned char) (n >> 16) & (0xFF);
- ((unsigned char*) p) [3] = (unsigned char) (n >> 24) & (0xFF);
-}
+ struct Context *wWriter = (struct Context *)ctx;
+ if(!wWriter)
+ return;
-void wave_close( void )
-{
- if ( file )
+ if(wWriter->m_file)
{
/* generate header */
unsigned char h [header_size] =
{
- 'R','I','F','F',
- 0,0,0,0, /* length of rest of file */
- 'W','A','V','E',
- 'f','m','t',' ',
- 0x10,0,0,0, /* size of fmt chunk */
- 1,0, /* uncompressed format */
- 0,0, /* channel count */
- 0,0,0,0, /* sample rate */
- 0,0,0,0, /* bytes per second */
- 0,0, /* bytes per sample frame */
- 16,0, /* bits per sample */
- 'd','a','t','a',
- 0,0,0,0, /* size of sample data */
+ 'R', 'I', 'F', 'F',
+ 0, 0, 0, 0, /* length of rest of file */
+ 'W', 'A', 'V', 'E',
+ 'f', 'm', 't', ' ',
+ 0x10, 0, 0, 0, /* size of fmt chunk */
+ 1, 0, /* uncompressed format */
+ 0, 0, /* channel count */
+ 0, 0, 0, 0, /* sample rate */
+ 0, 0, 0, 0, /* bytes per second */
+ 0, 0, /* bytes per sample frame */
+ 16, 0, /* bits per sample */
+ 'd', 'a', 't', 'a',
+ 0, 0, 0, 0, /* size of sample data */
/* ... */ /* sample data */
};
- long ds = sample_count_ * (long)sizeof (sample_t);
- int frame_size = chan_count * (long)sizeof (sample_t);
+ long ds = wWriter->m_sample_count * (long)sizeof(sample_t);
+ int frame_size = wWriter->m_chan_count * (long)sizeof(sample_t);
- set_le32( h + 0x04, header_size - 8 + ds );
- h [0x16] = (unsigned char)chan_count;
- set_le32( h + 0x18, (unsigned long)sample_rate_ );
- set_le32( h + 0x1C, (unsigned long)sample_rate_ * (unsigned long)frame_size );
+ set_le32(h + 0x04, header_size - 8 + ds);
+ h [0x16] = (unsigned char)wWriter->m_chan_count;
+ set_le32(h + 0x18, (unsigned long)wWriter->m_sample_rate);
+ set_le32(h + 0x1C, (unsigned long)wWriter->m_sample_rate * (unsigned long)frame_size);
h [0x20] = (unsigned char)frame_size;
- set_le32( h + 0x28, (unsigned long)ds );
+ set_le32(h + 0x28, (unsigned long)ds);
- flush_();
+ flush_(wWriter);
/* write header */
- fseek( file, 0, SEEK_SET );
- fwrite( h, header_size, 1, file );
- fclose( file );
- file = 0;
- free( buf );
- buf = 0;
+ fseek(wWriter->m_file, 0, SEEK_SET);
+ fwrite(h, header_size, 1, wWriter->m_file);
+ fclose(wWriter->m_file);
+ wWriter->m_file = 0;
+ free(wWriter->m_buf);
+ wWriter->m_buf = 0;
}
+ free(wWriter);
}
diff --git a/utils/midiplay/wave_writer.h b/utils/midiplay/wave_writer.h
index 6d49718..17318c3 100755
--- a/utils/midiplay/wave_writer.h
+++ b/utils/midiplay/wave_writer.h
@@ -5,17 +5,23 @@
#define WAVE_WRITER_H
#ifdef __cplusplus
- extern "C" {
+extern "C" {
#endif
-int wave_open( long sample_rate, const char* filename );
-void wave_enable_stereo( void );
-void wave_write( short const* in, long count );
-long wave_sample_count( void );
-void wave_close( void );
+int wave_open(long sample_rate, const char *filename);
+void wave_enable_stereo(void);
+void wave_write(short const *in, long count);
+long wave_sample_count(void);
+void wave_close(void);
+
+void *ctx_wave_open(long sample_rate, const char *filename);
+void ctx_wave_enable_stereo(void *ctx);
+void ctx_wave_write(void *ctx, short const *in, long count);
+long ctx_wave_sample_count(void *ctx);
+void ctx_wave_close(void *ctx);
#ifdef __cplusplus
- }
+}
#endif
#endif