From b178e1905ba0487583b40817d9a54f0fe2fd1a71 Mon Sep 17 00:00:00 2001 From: mahlzeit Date: Thu, 13 May 2004 19:54:00 +0000 Subject: [PATCH] Implemented BMidiSynthFile. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7571 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/midi/MidiStore.h | 12 ++++- headers/os/midi/MidiSynthFile.h | 6 ++- src/kits/midi/MidiStore.cpp | 57 ++++++++++++++++++++++-- src/kits/midi/MidiSynthFile.cpp | 79 ++++++++++++++++++++------------- src/kits/midi/SoftSynth.cpp | 18 ++++++-- src/kits/midi/Synth.cpp | 11 ++++- 6 files changed, 140 insertions(+), 43 deletions(-) diff --git a/headers/os/midi/MidiStore.h b/headers/os/midi/MidiStore.h index 038de7e962..2a1c4cdd94 100644 --- a/headers/os/midi/MidiStore.h +++ b/headers/os/midi/MidiStore.h @@ -4,6 +4,7 @@ #include #include +#include struct entry_ref; @@ -69,6 +70,8 @@ public: private: + friend class BMidiSynthFile; + virtual void _ReservedMidiStore1(); virtual void _ReservedMidiStore2(); virtual void _ReservedMidiStore3(); @@ -117,7 +120,14 @@ private: uint16 format; uint16 _reserved1[1]; - uint32 _reserved2[16]; + + synth_file_hook hookFunc; + int32 hookArg; + bool looping; + bool paused; + bool finished; + + uint32 _reserved2[13]; }; #endif // _MIDI_STORE_H diff --git a/headers/os/midi/MidiSynthFile.h b/headers/os/midi/MidiSynthFile.h index 67799d5039..9f2e67844a 100644 --- a/headers/os/midi/MidiSynthFile.h +++ b/headers/os/midi/MidiSynthFile.h @@ -8,6 +8,8 @@ typedef void (*synth_file_hook)(int32 arg); +class BMidiStore; + class BMidiSynthFile : public BMidiSynth { public: @@ -55,7 +57,9 @@ private: virtual void _ReservedMidiSynthFile2(); virtual void _ReservedMidiSynthFile3(); - uint32 _reserved[4]; + BMidiStore* store; + + int32 _reserved[3]; }; #endif // _MIDI_SYNTH_FILE diff --git a/src/kits/midi/MidiStore.cpp b/src/kits/midi/MidiStore.cpp index ce9f0e4e85..2507938f3b 100644 --- a/src/kits/midi/MidiStore.cpp +++ b/src/kits/midi/MidiStore.cpp @@ -80,6 +80,10 @@ BMidiStore::BMidiStore() beatsPerMinute = 60; ticksPerBeat = 240; file = NULL; + hookFunc = NULL; + looping = false; + paused = false; + finished = false; } //------------------------------------------------------------------------------ @@ -421,20 +425,58 @@ void BMidiStore::_ReservedMidiStore3() { } void BMidiStore::Run() { + // This rather compilicated Run() loop is not only used by BMidiStore + // but also by BMidiSynthFile. The "paused", "finished", and "looping" + // flags, and the "stop hook" are especially provided for the latter. + + paused = false; + finished = false; + int32 timeAdjust; + uint32 baseTime; bool firstEvent = true; + bool resetTime = false; while (KeepRunning()) { + if (paused) + { + resetTime = true; + snooze(100000); + continue; + } + BMidiEvent* event = EventAt(currentEvent); - if (event == NULL) { return; } + + if (event == NULL) // no more events + { + if (looping) + { + resetTime = true; + currentEvent = 0; + } + else + { + break; + } + } if (firstEvent) { startTime = B_NOW; - timeAdjust = startTime - GetEventTime(event); - SprayEvent(event, startTime); + baseTime = startTime; + } + else if (resetTime) + { + baseTime = B_NOW; + } + + if (firstEvent || resetTime) + { + timeAdjust = baseTime - GetEventTime(event); + SprayEvent(event, baseTime); firstEvent = false; + resetTime = false; } else { @@ -443,6 +485,14 @@ void BMidiStore::Run() ++currentEvent; } + + finished = true; + paused = false; + + if (hookFunc != NULL) + { + (*hookFunc)(hookArg); + } } //------------------------------------------------------------------------------ @@ -1034,4 +1084,5 @@ void BMidiStore::WriteMetaEvent(BMidiEvent* event) } } + //------------------------------------------------------------------------------ diff --git a/src/kits/midi/MidiSynthFile.cpp b/src/kits/midi/MidiSynthFile.cpp index 9dbf942e5f..b4dc687756 100644 --- a/src/kits/midi/MidiSynthFile.cpp +++ b/src/kits/midi/MidiSynthFile.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2002-2003 Matthijs Hollemans + * Copyright (c) 2002-2004 Matthijs Hollemans + * Copyright (c) 2003 Jerome Leveque * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,95 +22,107 @@ */ #include "debug.h" +#include "MidiStore.h" #include "MidiSynthFile.h" // ----------------------------------------------------------------------------- BMidiSynthFile::BMidiSynthFile() { - UNIMPLEMENTED + store = new BMidiStore(); } // ----------------------------------------------------------------------------- BMidiSynthFile::~BMidiSynthFile() { - UNIMPLEMENTED + Stop(); + delete store; } // ----------------------------------------------------------------------------- status_t BMidiSynthFile::LoadFile(const entry_ref* midi_entry_ref) { - UNIMPLEMENTED - return B_ERROR; + if (midi_entry_ref == NULL) + { + return B_BAD_VALUE; + } + + EnableInput(true, false); + store->finished = true; + + // TODO: figure out which instruments are used by the MIDI file, + // and load them one-by-one (add a method in BMidiStore for this). + + return store->Import(midi_entry_ref); } // ----------------------------------------------------------------------------- void BMidiSynthFile::UnloadFile(void) { - UNIMPLEMENTED + delete store; + store = new BMidiStore(); } // ----------------------------------------------------------------------------- status_t BMidiSynthFile::Start(void) { - UNIMPLEMENTED - return B_ERROR; + store->Connect(this); + store->SetCurrentEvent(0); + return store->Start(); } // ----------------------------------------------------------------------------- void BMidiSynthFile::Stop(void) { - UNIMPLEMENTED + store->Stop(); + store->Disconnect(this); } // ----------------------------------------------------------------------------- void BMidiSynthFile::Fade(void) { - UNIMPLEMENTED + Stop(); // really quick fade :P } // ----------------------------------------------------------------------------- void BMidiSynthFile::Pause(void) { - UNIMPLEMENTED + store->paused = true; } // ----------------------------------------------------------------------------- void BMidiSynthFile::Resume(void) { - UNIMPLEMENTED + store->paused = false; } // ----------------------------------------------------------------------------- int32 BMidiSynthFile::Duration(void) const { - UNIMPLEMENTED - return 0; + return store->DeltaOfEvent(store->CountEvents()); } // ----------------------------------------------------------------------------- int32 BMidiSynthFile::Position(int32 ticks) const { - UNIMPLEMENTED - return 0; + return store->EventAtDelta(ticks); } // ----------------------------------------------------------------------------- int32 BMidiSynthFile::Seek() { - UNIMPLEMENTED - return 0; + return store->CurrentEvent(); } // ----------------------------------------------------------------------------- @@ -117,80 +130,82 @@ int32 BMidiSynthFile::Seek() status_t BMidiSynthFile::GetPatches( int16* pArray768, int16* pReturnedCount) const { - UNIMPLEMENTED - return B_ERROR; + // TODO: when loading of instruments in LoadFile() has been + // implemented, we can finish this function too. + + *pReturnedCount = 0; + return B_OK; } // ----------------------------------------------------------------------------- void BMidiSynthFile::SetFileHook(synth_file_hook pSongHook, int32 arg) { - UNIMPLEMENTED + store->hookFunc = pSongHook; + store->hookArg = arg; } // ----------------------------------------------------------------------------- bool BMidiSynthFile::IsFinished(void) const { - UNIMPLEMENTED - return false; + return store->finished; } // ----------------------------------------------------------------------------- void BMidiSynthFile::ScaleTempoBy(double tempoFactor) { - UNIMPLEMENTED + store->SetTempo((int32) (Tempo() * tempoFactor)); } // ----------------------------------------------------------------------------- void BMidiSynthFile::SetTempo(int32 newTempoBPM) { - UNIMPLEMENTED + store->SetTempo(newTempoBPM); } // ----------------------------------------------------------------------------- int32 BMidiSynthFile::Tempo(void) const { - UNIMPLEMENTED - return 0; + return store->Tempo(); } // ----------------------------------------------------------------------------- void BMidiSynthFile::EnableLooping(bool loop) { - UNIMPLEMENTED + store->looping = loop; } // ----------------------------------------------------------------------------- void BMidiSynthFile::MuteTrack(int16 track, bool do_mute) { - UNIMPLEMENTED + fprintf(stderr, "[midi] MuteTrack is broken; don't use it\n"); } // ----------------------------------------------------------------------------- void BMidiSynthFile::GetMuteMap(char* pTracks) const { - UNIMPLEMENTED + fprintf(stderr, "[midi] GetMuteMap is broken; don't use it\n"); } // ----------------------------------------------------------------------------- void BMidiSynthFile::SoloTrack(int16 track, bool do_solo) { - UNIMPLEMENTED + fprintf(stderr, "[midi] SoloTrack is broken; don't use it\n"); } // ----------------------------------------------------------------------------- void BMidiSynthFile::GetSoloMap(char* pTracks) const { - UNIMPLEMENTED + fprintf(stderr, "[midi] GetSoloMap is broken; don't use it\n"); } // ----------------------------------------------------------------------------- diff --git a/src/kits/midi/SoftSynth.cpp b/src/kits/midi/SoftSynth.cpp index 3cbea5b563..45d273e3a3 100644 --- a/src/kits/midi/SoftSynth.cpp +++ b/src/kits/midi/SoftSynth.cpp @@ -298,6 +298,7 @@ void BSoftSynth::Resume(void) void BSoftSynth::NoteOff( uchar channel, uchar note, uchar velocity, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -306,6 +307,7 @@ void BSoftSynth::NoteOff( void BSoftSynth::NoteOn( uchar channel, uchar note, uchar velocity, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -314,6 +316,7 @@ void BSoftSynth::NoteOn( void BSoftSynth::KeyPressure( uchar channel, uchar note, uchar pressure, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -322,6 +325,7 @@ void BSoftSynth::KeyPressure( void BSoftSynth::ControlChange( uchar channel, uchar controlNumber, uchar controlValue, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -330,22 +334,23 @@ void BSoftSynth::ControlChange( void BSoftSynth::ProgramChange( uchar channel, uchar programNumber, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } //------------------------------------------------------------------------------ -void BSoftSynth::ChannelPressure( - uchar channel, uchar pressure, uint32 time) +void BSoftSynth::ChannelPressure(uchar channel, uchar pressure, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } //------------------------------------------------------------------------------ -void BSoftSynth::PitchBend( - uchar channel, uchar lsb, uchar msb, uint32 time) +void BSoftSynth::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -353,6 +358,7 @@ void BSoftSynth::PitchBend( void BSoftSynth::SystemExclusive(void* data, size_t length, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -361,6 +367,7 @@ void BSoftSynth::SystemExclusive(void* data, size_t length, uint32 time) void BSoftSynth::SystemCommon( uchar status, uchar data1, uchar data2, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -368,6 +375,7 @@ void BSoftSynth::SystemCommon( void BSoftSynth::SystemRealTime(uchar status, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -375,6 +383,7 @@ void BSoftSynth::SystemRealTime(uchar status, uint32 time) void BSoftSynth::TempoChange(int32 beatsPerMinute, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } @@ -382,6 +391,7 @@ void BSoftSynth::TempoChange(int32 beatsPerMinute, uint32 time) void BSoftSynth::AllNotesOff(bool justChannel, uint32 time) { + snooze_until(time * (bigtime_t) 1000, B_SYSTEM_TIMEBASE); UNIMPLEMENTED } diff --git a/src/kits/midi/Synth.cpp b/src/kits/midi/Synth.cpp index 685205729f..aaebd89e14 100644 --- a/src/kits/midi/Synth.cpp +++ b/src/kits/midi/Synth.cpp @@ -21,6 +21,8 @@ * DEALINGS IN THE SOFTWARE. */ +#include + #include "debug.h" #include "Synth.h" #include "SoftSynth.h" @@ -229,8 +231,13 @@ double BSynth::SampleVolume(void) const status_t BSynth::GetAudio( int16* pLeft, int16* pRight, int32 max_samples) const { - fprintf(stderr, "[midi] GetAudio is not supported\n"); - return B_ERROR; + // We don't print a "not supported" message here. That would cause + // significant slowdowns because applications ask for this many times. + + memset(pLeft, 0, max_samples * sizeof(int16)); + memset(pRight, 0, max_samples * sizeof(int16)); + + return max_samples; } //------------------------------------------------------------------------------