#include "bass.h" // BASS core API #include "bassmidi.h" // BASSMIDI extension API #include #include #include void WriteWAVHeader(std::ofstream &file, DWORD length) { DWORD dataChunkSize = length; DWORD fmtChunkSize = 16; DWORD sampleRate = 44100; WORD bitsPerSample = 16; WORD channels = 2; DWORD byteRate = sampleRate * channels * bitsPerSample / 8; WORD blockAlign = channels * bitsPerSample / 8; DWORD totalSize = 4 + (8 + fmtChunkSize) + (8 + dataChunkSize); file.write("RIFF", 4); file.write(reinterpret_cast(&totalSize), 4); file.write("WAVE", 4); // fmt chunk file.write("fmt ", 4); file.write(reinterpret_cast(&fmtChunkSize), 4); WORD formatTag = 1; // PCM file.write(reinterpret_cast(&formatTag), 2); file.write(reinterpret_cast(&channels), 2); file.write(reinterpret_cast(&sampleRate), 4); file.write(reinterpret_cast(&byteRate), 4); file.write(reinterpret_cast(&blockAlign), 2); file.write(reinterpret_cast(&bitsPerSample), 2); // data chunk file.write("data", 4); file.write(reinterpret_cast(&dataChunkSize), 4); } int main() { // 1) Initialize BASS: default device, 44100 Hz, no flags if (!BASS_Init(-1, 44100, 0, NULL, NULL)) { std::cerr << "BASS_Init error: " << BASS_ErrorGetCode() << std::endl; return 1; } // 2) Load the SF2PACK soundfont HSOUNDFONT sfont = BASS_MIDI_FontInit("Chorium_fork.sf2", 0); if (!sfont) { std::cerr << "BASS_MIDI_FontInit error: " << BASS_ErrorGetCode() << std::endl; BASS_Free(); return 1; } // Create decoding stream (no playback) HSTREAM midiStream = BASS_MIDI_StreamCreateFile(FALSE, "Rapapara_POL_07753.mid", 0, 0, BASS_STREAM_DECODE | BASS_SAMPLE_FLOAT, 44100); if (!midiStream) { std::cerr << "BASS_MIDI_StreamCreateFile error: " << BASS_ErrorGetCode() << std::endl; BASS_MIDI_FontFree(sfont); BASS_Free(); return 1; } // Assign soundfont BASS_MIDI_FONT fontConfig{ sfont, -1, 0 }; if (!BASS_MIDI_StreamSetFonts(midiStream, &fontConfig, 1)) { std::cerr << "BASS_MIDI_StreamSetFonts error: " << BASS_ErrorGetCode() << std::endl; BASS_StreamFree(midiStream); BASS_MIDI_FontFree(sfont); BASS_Free(); return 1; } std::ofstream wav("output.wav", std::ios::binary); if (!wav) { std::cerr << "Can't open output.wav for writing" << std::endl; return 1; } DWORD totalBytes = 0; const int bufferSize = 44100 * 2 * sizeof(float); // 1 second float stereo float buffer[44100 * 2]; while (true) { int bytes = BASS_ChannelGetData(midiStream, buffer, bufferSize); if (bytes <= 0) break; // Convert float samples to 16-bit PCM short pcm[44100 * 2]; for (int i = 0; i < bytes / 4; ++i) { float sample = buffer[i] * 32767.0f; if (sample > 32767.0f) sample = 32767.0f; if (sample < -32768.0f) sample = -32768.0f; pcm[i] = static_cast(sample); } wav.write(reinterpret_cast(pcm), bytes / 2); // float->16bit halves size totalBytes += bytes / 2; } wav.seekp(0); WriteWAVHeader(wav, totalBytes); wav.close(); std::cout << "Exported to output.wav" << std::endl; // 6) Clean up BASS_StreamFree(midiStream); // free stream BASS_MIDI_FontFree(sfont); // unload soundfont BASS_Free(); // shut down BASS return 0; }