From 81f905ea76f0efb6ea35331bd1fe476f14f804de Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Mon, 1 Jul 2019 05:01:55 +0300 Subject: First working of new database // not so stable, needs a polishing, however, multibank from embedded 72'th bank (DMXOPL3) works! --- utils/gen_adldata/CMakeLists.txt | 5 + utils/gen_adldata/gen_adldata.cc | 3 + utils/gen_adldata/measurer.cpp | 155 +++++++++++++++++++--------- utils/gen_adldata/measurer.h | 6 +- utils/gen_adldata/progs_cache.h | 7 ++ utils/midiplay/wave_writer.c | 214 ++++++++++++++++++++++++--------------- utils/midiplay/wave_writer.h | 20 ++-- 7 files changed, 266 insertions(+), 144 deletions(-) (limited to 'utils') 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 +#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 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(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(toUint16LE(data_k + 0)); v.ms_sound_koff = static_cast(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((v.ms_sound_kon >> 0) & 0xFF), static_cast((v.ms_sound_kon >> 8) & 0xFF), static_cast((v.ms_sound_koff >> 0) & 0xFF), - static_cast((v.ms_sound_koff >> 8) & 0xFF) + static_cast((v.ms_sound_koff >> 8) & 0xFF), + static_cast(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(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 DurationInfoCache; typedef std::map 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 -- cgit v1.2.3