From a5316c211d208c903654cd359fe5a8323a9ca0f1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 24 Feb 2018 18:25:04 +0100 Subject: [PATCH] - Moved the MIDI WAVE writer device to its own source file. --- src/CMakeLists.txt | 3 +- .../mididevices/music_timidity_mididevice.cpp | 147 ------------- .../music_wavewriter_mididevice.cpp | 208 ++++++++++++++++++ 3 files changed, 210 insertions(+), 148 deletions(-) create mode 100644 src/sound/mididevices/music_wavewriter_mididevice.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 22ea7df918..a35b3f3bfd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -802,7 +802,6 @@ set( FASTMATH_SOURCES sound/music_midi_base.cpp sound/oalsound.cpp sound/sndfile_decoder.cpp - sound/mididevices/music_timiditypp_mididevice.cpp sound/timiditypp/fft4g.cpp sound/timiditypp/reverb.cpp gl/utility/gl_clock.cpp @@ -1139,10 +1138,12 @@ set (PCH_SOURCES sound/i_soundfont.cpp sound/mididevices/music_opldumper_mididevice.cpp sound/mididevices/music_opl_mididevice.cpp + sound/mididevices/music_timiditypp_mididevice.cpp sound/mididevices/music_fluidsynth_mididevice.cpp sound/mididevices/music_softsynth_mididevice.cpp sound/mididevices/music_timidity_mididevice.cpp sound/mididevices/music_wildmidi_mididevice.cpp + sound/mididevices/music_wavewriter_mididevice.cpp sound/midisources/midisource.cpp sound/midisources/midisource_mus.cpp sound/midisources/midisource_smf.cpp diff --git a/src/sound/mididevices/music_timidity_mididevice.cpp b/src/sound/mididevices/music_timidity_mididevice.cpp index ba2a3b915e..675fee1262 100644 --- a/src/sound/mididevices/music_timidity_mididevice.cpp +++ b/src/sound/mididevices/music_timidity_mididevice.cpp @@ -41,31 +41,10 @@ #include "w_wad.h" #include "v_text.h" #include "timidity/timidity.h" -#include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- -// MIDI file played with TiMidity++ and possibly streamed through the Sound System - -struct FmtChunk -{ - uint32_t ChunkID; - uint32_t ChunkLen; - uint16_t FormatTag; - uint16_t Channels; - uint32_t SamplesPerSec; - uint32_t AvgBytesPerSec; - uint16_t BlockAlign; - uint16_t BitsPerSample; - uint16_t ExtensionSize; - uint16_t ValidBitsPerSample; - uint32_t ChannelMask; - uint32_t SubFormatA; - uint16_t SubFormatB; - uint16_t SubFormatC; - uint8_t SubFormatD[8]; -}; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -238,129 +217,3 @@ FString TimidityMIDIDevice::GetStats() } return out; } - -//========================================================================== -// -// TimidityWaveWriterMIDIDevice Constructor -// -//========================================================================== - -MIDIWaveWriter::MIDIWaveWriter(const char *filename, MIDIDevice *playdevice, int rate) -{ - File = FileWriter::Open(filename); - playDevice = (SoftSynthMIDIDevice*) playdevice; - if (File != nullptr) - { // Write wave header - uint32_t work[3]; - FmtChunk fmt; - - work[0] = MAKE_ID('R','I','F','F'); - work[1] = 0; // filled in later - work[2] = MAKE_ID('W','A','V','E'); - if (4*3 != File->Write(work, 4 * 3)) goto fail; - - - playDevice->SetSampleRate(rate); - playDevice->CalcTickRate(); - rate = playDevice->GetSampleRate(); // read back what the device made of it. - fmt.ChunkID = MAKE_ID('f','m','t',' '); - fmt.ChunkLen = LittleLong(uint32_t(sizeof(fmt) - 8)); - fmt.FormatTag = LittleShort(0xFFFE); // WAVE_FORMAT_EXTENSIBLE - fmt.Channels = LittleShort(2); - fmt.SamplesPerSec = LittleLong(rate); - fmt.AvgBytesPerSec = LittleLong(rate * 8); - fmt.BlockAlign = LittleShort(8); - fmt.BitsPerSample = LittleShort(32); - fmt.ExtensionSize = LittleShort(2 + 4 + 16); - fmt.ValidBitsPerSample = LittleShort(32); - fmt.ChannelMask = LittleLong(3); - fmt.SubFormatA = LittleLong(0x00000003); // Set subformat to KSDATAFORMAT_SUBTYPE_IEEE_FLOAT - fmt.SubFormatB = LittleShort(0x0000); - fmt.SubFormatC = LittleShort(0x0010); - fmt.SubFormatD[0] = 0x80; - fmt.SubFormatD[1] = 0x00; - fmt.SubFormatD[2] = 0x00; - fmt.SubFormatD[3] = 0xaa; - fmt.SubFormatD[4] = 0x00; - fmt.SubFormatD[5] = 0x38; - fmt.SubFormatD[6] = 0x9b; - fmt.SubFormatD[7] = 0x71; - if (sizeof(fmt) != File->Write(&fmt, sizeof(fmt))) goto fail; - - work[0] = MAKE_ID('d','a','t','a'); - work[1] = 0; // filled in later - if (8 !=File->Write(work, 8)) goto fail; - - return; -fail: - Printf("Failed to write %s: %s\n", filename, strerror(errno)); - delete File; - File = nullptr; - } -} - -//========================================================================== -// -// TimidityWaveWriterMIDIDevice Destructor -// -//========================================================================== - -MIDIWaveWriter::~MIDIWaveWriter() -{ - if (File != nullptr) - { - long pos = File->Tell(); - uint32_t size; - - // data chunk size - size = LittleLong(uint32_t(pos - 8)); - if (0 == File->Seek(4, SEEK_SET)) - { - if (4 == File->Write(&size, 4)) - { - size = LittleLong(uint32_t(pos - 12 - sizeof(FmtChunk) - 8)); - if (0 == File->Seek(4 + sizeof(FmtChunk) + 4, SEEK_CUR)) - { - if (4 == File->Write(&size, 4)) - { - delete File; - return; - } - } - } - } - Printf("Could not finish writing wave file: %s\n", strerror(errno)); - delete File; - } -} - -//========================================================================== -// -// TimidityWaveWriterMIDIDevice :: Resume -// -//========================================================================== - -int MIDIWaveWriter::Resume() -{ - float writebuffer[4096]; - - while (ServiceStream(writebuffer, sizeof(writebuffer))) - { - if (File->Write(writebuffer, sizeof(writebuffer)) != sizeof(writebuffer)) - { - Printf("Could not write entire wave file: %s\n", strerror(errno)); - return 1; - } - } - return 0; -} - -//========================================================================== -// -// TimidityWaveWriterMIDIDevice Stop -// -//========================================================================== - -void MIDIWaveWriter::Stop() -{ -} diff --git a/src/sound/mididevices/music_wavewriter_mididevice.cpp b/src/sound/mididevices/music_wavewriter_mididevice.cpp new file mode 100644 index 0000000000..44e263bdfe --- /dev/null +++ b/src/sound/mididevices/music_wavewriter_mididevice.cpp @@ -0,0 +1,208 @@ +/* +** music_wavewriter_mididevice.cpp +** Dumos a MIDI to a wave file by using one of the other software synths. +** +**--------------------------------------------------------------------------- +** Copyright 2008 Randy Heit +** Copyright 2018 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +// HEADER FILES ------------------------------------------------------------ + +#include "i_musicinterns.h" +#include "templates.h" +#include "doomdef.h" +#include "m_swap.h" +#include "w_wad.h" +#include "v_text.h" +#include "timidity/timidity.h" +#include + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +struct FmtChunk +{ + uint32_t ChunkID; + uint32_t ChunkLen; + uint16_t FormatTag; + uint16_t Channels; + uint32_t SamplesPerSec; + uint32_t AvgBytesPerSec; + uint16_t BlockAlign; + uint16_t BitsPerSample; + uint16_t ExtensionSize; + uint16_t ValidBitsPerSample; + uint32_t ChannelMask; + uint32_t SubFormatA; + uint16_t SubFormatB; + uint16_t SubFormatC; + uint8_t SubFormatD[8]; +}; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// TimidityWaveWriterMIDIDevice Constructor +// +//========================================================================== + +MIDIWaveWriter::MIDIWaveWriter(const char *filename, MIDIDevice *playdevice, int rate) +{ + File = FileWriter::Open(filename); + playDevice = (SoftSynthMIDIDevice*) playdevice; + if (File != nullptr) + { // Write wave header + uint32_t work[3]; + FmtChunk fmt; + + work[0] = MAKE_ID('R','I','F','F'); + work[1] = 0; // filled in later + work[2] = MAKE_ID('W','A','V','E'); + if (4*3 != File->Write(work, 4 * 3)) goto fail; + + + playDevice->SetSampleRate(rate); + playDevice->CalcTickRate(); + rate = playDevice->GetSampleRate(); // read back what the device made of it. + fmt.ChunkID = MAKE_ID('f','m','t',' '); + fmt.ChunkLen = LittleLong(uint32_t(sizeof(fmt) - 8)); + fmt.FormatTag = LittleShort(0xFFFE); // WAVE_FORMAT_EXTENSIBLE + fmt.Channels = LittleShort(2); + fmt.SamplesPerSec = LittleLong(rate); + fmt.AvgBytesPerSec = LittleLong(rate * 8); + fmt.BlockAlign = LittleShort(8); + fmt.BitsPerSample = LittleShort(32); + fmt.ExtensionSize = LittleShort(2 + 4 + 16); + fmt.ValidBitsPerSample = LittleShort(32); + fmt.ChannelMask = LittleLong(3); + fmt.SubFormatA = LittleLong(0x00000003); // Set subformat to KSDATAFORMAT_SUBTYPE_IEEE_FLOAT + fmt.SubFormatB = LittleShort(0x0000); + fmt.SubFormatC = LittleShort(0x0010); + fmt.SubFormatD[0] = 0x80; + fmt.SubFormatD[1] = 0x00; + fmt.SubFormatD[2] = 0x00; + fmt.SubFormatD[3] = 0xaa; + fmt.SubFormatD[4] = 0x00; + fmt.SubFormatD[5] = 0x38; + fmt.SubFormatD[6] = 0x9b; + fmt.SubFormatD[7] = 0x71; + if (sizeof(fmt) != File->Write(&fmt, sizeof(fmt))) goto fail; + + work[0] = MAKE_ID('d','a','t','a'); + work[1] = 0; // filled in later + if (8 !=File->Write(work, 8)) goto fail; + + return; +fail: + Printf("Failed to write %s: %s\n", filename, strerror(errno)); + delete File; + File = nullptr; + } +} + +//========================================================================== +// +// TimidityWaveWriterMIDIDevice Destructor +// +//========================================================================== + +MIDIWaveWriter::~MIDIWaveWriter() +{ + if (File != nullptr) + { + long pos = File->Tell(); + uint32_t size; + + // data chunk size + size = LittleLong(uint32_t(pos - 8)); + if (0 == File->Seek(4, SEEK_SET)) + { + if (4 == File->Write(&size, 4)) + { + size = LittleLong(uint32_t(pos - 12 - sizeof(FmtChunk) - 8)); + if (0 == File->Seek(4 + sizeof(FmtChunk) + 4, SEEK_CUR)) + { + if (4 == File->Write(&size, 4)) + { + delete File; + return; + } + } + } + } + Printf("Could not finish writing wave file: %s\n", strerror(errno)); + delete File; + } +} + +//========================================================================== +// +// TimidityWaveWriterMIDIDevice :: Resume +// +//========================================================================== + +int MIDIWaveWriter::Resume() +{ + float writebuffer[4096]; + + while (ServiceStream(writebuffer, sizeof(writebuffer))) + { + if (File->Write(writebuffer, sizeof(writebuffer)) != sizeof(writebuffer)) + { + Printf("Could not write entire wave file: %s\n", strerror(errno)); + return 1; + } + } + return 0; +} + +//========================================================================== +// +// TimidityWaveWriterMIDIDevice Stop +// +//========================================================================== + +void MIDIWaveWriter::Stop() +{ +}