Skip to content

Commit

Permalink
MIDI: native midiout system
Browse files Browse the repository at this point in the history
  • Loading branch information
tyrone-sudeium authored and Ghabry committed Jul 13, 2021
1 parent 6b30d38 commit 7e3c97a
Show file tree
Hide file tree
Showing 22 changed files with 1,138 additions and 15 deletions.
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ add_library(${PROJECT_NAME} STATIC
src/audio.h
src/audio_midi.cpp
src/audio_midi.h
src/audio_midiout.cpp
src/audio_midiout.h
src/audio_midiout_device.cpp
src/audio_midiout_device.h
src/audio_resampler.cpp
src/audio_resampler.h
src/audio_sdl.cpp
Expand Down Expand Up @@ -533,13 +537,17 @@ if(WIN32)
target_sources(${PROJECT_NAME} PRIVATE
src/registry.cpp
src/platform/windows/utils.cpp
src/platform/windows/utils.h)
src/platform/windows/utils.h
src/platform/windows/midiout_device_win32.cpp
src/platform/windows/midiout_device_win32.h)
endif()

if(APPLE)
target_sources(${PROJECT_NAME} PRIVATE
src/platform/macos/utils.mm
src/platform/macos/utils.h)
src/platform/macos/utils.h
src/platform/macos/midiout_device_coreaudio.cpp
src/platform/macos/midiout_device_coreaudio.h)

find_library(MACOSFOUNDATION Foundation)
target_link_libraries(${PROJECT_NAME} ${MACOSFOUNDATION})
Expand Down
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ libeasyrpg_player_a_SOURCES = \
src/audio_generic.h \
src/audio_midi.cpp \
src/audio_midi.h \
src/audio_midiout.cpp \
src/audio_midiout.h \
src/audio_midiout_device.cpp \
src/audio_midiout_device.h \
src/audio_resampler.cpp \
src/audio_resampler.h \
src/audio_sdl.cpp \
Expand Down
80 changes: 70 additions & 10 deletions src/audio_generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ std::vector<float> GenericAudio::mixer_buffer = {};

GenericAudio::GenericAudio() {
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.midiout) {
BGM_Channel.midiout->Reset();
}
BGM_Channel.midiout.reset();
BGM_Channel.decoder.reset();
}
for (auto& SE_Channel : SE_Channels) {
Expand All @@ -51,9 +55,10 @@ GenericAudio::~GenericAudio() {

void GenericAudio::BGM_Play(Filesystem_Stream::InputStream stream, int volume, int pitch, int fadein) {
bool bgm_set = false;
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
BGM_Channel.stopped = true; //Stop all running background music
if (!BGM_Channel.decoder && !bgm_set) {
if (!BGM_Channel.decoder && !BGM_Channel.midiout && !bgm_set) {
//If there is an unused bgm channel
bgm_set = true;
LockMutex();
Expand All @@ -62,31 +67,49 @@ void GenericAudio::BGM_Play(Filesystem_Stream::InputStream stream, int volume, i
PlayOnChannel(BGM_Channel, std::move(stream), volume, pitch, fadein);
}
}
UnlockMidiOutMutex();
}

void GenericAudio::BGM_Pause() {
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.decoder) {
if (BGM_Channel.decoder || BGM_Channel.midiout) {
if (BGM_Channel.midiout) {
BGM_Channel.midiout->Pause();
}
BGM_Channel.paused = true;
}
}
UnlockMidiOutMutex();
}

void GenericAudio::BGM_Resume() {
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.decoder) {
if (BGM_Channel.decoder || BGM_Channel.midiout) {
if (BGM_Channel.midiout) {
BGM_Channel.midiout->Resume();
}
BGM_Channel.paused = false;
}
}
UnlockMidiOutMutex();
}

void GenericAudio::BGM_Stop() {
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
BGM_Channel.stopped = true; //Stop all running background music
LockMutex();
BGM_Channel.decoder.reset();
UnlockMutex();
if (BGM_Channel.midiout) {
BGM_Channel.midiout->Reset();
BGM_Channel.midiout.reset();
} else if (BGM_Channel.decoder) {
LockMutex();
BGM_Channel.decoder.reset();
UnlockMutex();
}
}
UnlockMidiOutMutex();
}

bool GenericAudio::BGM_PlayedOnce() const {
Expand All @@ -105,43 +128,60 @@ bool GenericAudio::BGM_IsPlaying() const {
int GenericAudio::BGM_GetTicks() const {
unsigned ticks = 0;
LockMutex();
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.decoder) {
if (BGM_Channel.midiout) {
ticks = BGM_Channel.midiout->GetTicks();
} else if (BGM_Channel.decoder) {
ticks = BGM_Channel.decoder->GetTicks();
break;
}
}
UnlockMidiOutMutex();
UnlockMutex();
return ticks;
}

void GenericAudio::BGM_Fade(int fade) {
LockMutex();
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.decoder) {
if (BGM_Channel.midiout) {
BGM_Channel.midiout->SetFade(BGM_Channel.midiout->GetVolume(), 0, fade);
} else if (BGM_Channel.decoder) {
BGM_Channel.decoder->SetFade(BGM_Channel.decoder->GetVolume(), 0, fade);
}

}
UnlockMidiOutMutex();
UnlockMutex();
}

void GenericAudio::BGM_Volume(int volume) {
LockMutex();
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.decoder) {
if (BGM_Channel.midiout) {
BGM_Channel.midiout->SetVolume(volume);
} else if (BGM_Channel.decoder) {
BGM_Channel.decoder->SetVolume(volume);
}
}
UnlockMidiOutMutex();
UnlockMutex();
}

void GenericAudio::BGM_Pitch(int pitch) {
LockMutex();
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.decoder) {
if (BGM_Channel.midiout) {
BGM_Channel.midiout->SetPitch(pitch);
} else if (BGM_Channel.decoder) {
BGM_Channel.decoder->SetPitch(pitch);
}
}
UnlockMidiOutMutex();
UnlockMutex();
}

Expand All @@ -167,6 +207,16 @@ void GenericAudio::Update() {
// no-op, handled by the Decode function called through a thread
}

void GenericAudio::UpdateMidiOut(long long delta) {
LockMidiOutMutex();
for (auto& BGM_Channel : BGM_Channels) {
if (BGM_Channel.midiout && !BGM_Channel.paused) {
BGM_Channel.midiout->Update(delta);
}
}
UnlockMidiOutMutex();
}

void GenericAudio::SetFormat(int frequency, AudioDecoder::Format format, int channels) {
output_format.frequency = frequency;
output_format.format = format;
Expand All @@ -182,6 +232,16 @@ bool GenericAudio::PlayOnChannel(BgmChannel& chan, Filesystem_Stream::InputStrea
return false;
}

chan.midiout = MidiOut::Create(filestream);
if (chan.midiout && chan.midiout->Open(std::move(filestream))) {
chan.midiout->SetPitch(pitch);
chan.midiout->SetVolume(volume);
chan.midiout->SetFade(0, volume, fadein);
chan.midiout->SetLooping(true);
chan.paused = false;
return true;
}

chan.decoder = AudioDecoder::Create(filestream);
if (chan.decoder && chan.decoder->Open(std::move(filestream))) {
chan.decoder->SetPitch(pitch);
Expand Down
5 changes: 5 additions & 0 deletions src/audio_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "audio.h"
#include "audio_decoder.h"
#include "audio_secache.h"
#include "audio_midiout.h"

/**
* A software implementation for handling EasyRPG Audio utilizing the
Expand Down Expand Up @@ -54,17 +55,21 @@ struct GenericAudio : public AudioInterface {
void SE_Play(Filesystem_Stream::InputStream stream, int volume, int pitch) override;
void SE_Stop() override;
virtual void Update() override;
virtual void UpdateMidiOut(long long delta);

void SetFormat(int frequency, AudioDecoder::Format format, int channels);

virtual void LockMutex() const = 0;
virtual void UnlockMutex() const = 0;
virtual void LockMidiOutMutex() const = 0;
virtual void UnlockMidiOutMutex() const = 0;

void Decode(uint8_t* output_buffer, int buffer_length);

private:
struct BgmChannel {
std::unique_ptr<AudioDecoder> decoder;
std::unique_ptr<MidiOut> midiout;
bool paused;
bool stopped;
};
Expand Down
Loading

0 comments on commit 7e3c97a

Please sign in to comment.