#include #include "AudioPlayer.h" #include "../system/Timer.h" #include "../util/Asm.h" #define DMA_BUFFER_SIZE (SB_BUFFER_SIZE * 4) AudioPlayer audioPlayer; void radPlayerWriteReg(void *p, uint16_t reg, uint8_t data) { auto player = static_cast(p); player->writeOpl(reg, data); } void audioPlayerOnTimer() { audioPlayer.onTimer(); } AudioPlayer::AudioPlayer() { // Allocate twice the amount needed and select one half depending on whether it crosses a 64k boundary _dmaBuffer.size = (DMA_BUFFER_SIZE + 15) >> (4-1); _go32_dpmi_allocate_dos_memory(&_dmaBuffer); auto physFirst = (_dmaBuffer.rm_segment << 4) + _dmaBuffer.rm_offset; auto physSecond = physFirst + DMA_BUFFER_SIZE; auto pageFirst = physFirst >> 16; auto pageSecond = physSecond >> 16; if (pageFirst == pageSecond) { // Use first half _buffers = reinterpret_cast(physFirst); _dmaPage = pageFirst; _dmaOffset = physFirst & 0xFFFF; } else { // Use second half _buffers = reinterpret_cast(physSecond); _dmaPage = pageSecond; _dmaOffset = physSecond & 0xFFFF; } timer.setCallback(audioPlayerOnTimer); } AudioPlayer::~AudioPlayer() { timer.setCallback(nullptr); _go32_dpmi_free_dos_memory(&_dmaBuffer); } void AudioPlayer::playMusic(Music &music) { stopMusic(); _currentMusic = &music; _musicPlayer.Init(_currentMusic->getData(), radPlayerWriteReg, this); auto hz = _musicPlayer.GetHertz(); if (hz < 0) { stopMusic(); return; } // Start music playback timer.setFrequency(hz); resumeMusic(); } void AudioPlayer::stopMusic() { if (!_currentMusic) return; _musicPlayer.Stop(); _paused = true; _currentMusic = nullptr; } void AudioPlayer::pauseMusic() { _paused = true; } void AudioPlayer::resumeMusic() { if (!_currentMusic) return; _paused = false; } void AudioPlayer::playAudio(Audio &audio, int priority, int flags) { if (priority > AUDIO_MAX_PRIORITY) priority = AUDIO_MAX_PRIORITY; } bool AudioPlayer::isPlaying(const Audio &audio) { for (auto &channel : _channels) { if (channel.audio == &audio) return true; } return false; } void AudioPlayer::stopAudio(Audio &audio) { for (auto &channel : _channels) { if (channel.audio == &audio) { channel.audio = nullptr; channel.loop = false; } } } void AudioPlayer::stopAllAudio() { for (auto &channel : _channels) { channel.audio = nullptr; channel.loop = false; } } bool AudioPlayer::isPlaying(const Music &music) const { return _currentMusic == &music; } void AudioPlayer::writeOpl(uint16_t reg, uint8_t data) const { if (reg >= 0x100) { outb(_oplReg + 2, reg & 0xff); outb(_oplReg + 3, data); } else { outb(_oplReg, reg); outb(_oplReg + 1, data); } } void AudioPlayer::onTimer() { if (_paused) return; if (!_currentMusic) return; _musicPlayer.Update(); } void AudioPlayer::generateSamples() { } void AudioPlayer::copySamples() { // No data available - should not happen, but let's force generate a block if (_nextBufferReadIndex == _nextBufferWriteIndex) { generateSamples(); } dosmemput(_buffers, SB_BUFFER_SIZE, (_dmaBuffer.rm_segment << 4) + _nextBufferReadIndex * SB_BUFFER_SIZE); _nextBufferReadIndex = (_nextBufferReadIndex + 1) & 3; }