diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 61d179dd8..bd6811767 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -650,35 +650,6 @@ set( FASTMATH_SOURCES libsmackerdec/src/LogError.cpp libsmackerdec/src/SmackerDecoder.cpp - # This will go away once GZDoom's music backend has been plugged in. - libxmp-lite/src/common.c - libxmp-lite/src/control.c - libxmp-lite/src/dataio.c - libxmp-lite/src/effects.c - libxmp-lite/src/filter.c - libxmp-lite/src/format.c - libxmp-lite/src/hio.c - libxmp-lite/src/itsex.c - libxmp-lite/src/it_load.c - libxmp-lite/src/lfo.c - libxmp-lite/src/load.c - libxmp-lite/src/load_helpers.c - libxmp-lite/src/memio.c - libxmp-lite/src/mixer.c - libxmp-lite/src/mix_all.c - libxmp-lite/src/mod_load.c - libxmp-lite/src/mtm_load.c - libxmp-lite/src/period.c - libxmp-lite/src/player.c - libxmp-lite/src/read_event.c - libxmp-lite/src/s3m_load.c - libxmp-lite/src/sample.c - libxmp-lite/src/scan.c - libxmp-lite/src/smix.c - libxmp-lite/src/virtual.c - libxmp-lite/src/win32.c - libxmp-lite/src/xm_load.c - # The rest is only here because it is C, not C++ glad/src/glad.c @@ -694,7 +665,6 @@ set (PCH_SOURCES audiolib/src/driver_nosound.cpp audiolib/src/driver_sdl.cpp audiolib/src/driver_winmm.cpp - audiolib/src/flac.cpp audiolib/src/formats.cpp audiolib/src/fx_man.cpp audiolib/src/gmtimbre.cpp @@ -706,8 +676,6 @@ set (PCH_SOURCES audiolib/src/opl3.cpp audiolib/src/pitch.cpp audiolib/src/vorbis.cpp - audiolib/src/xa.cpp - audiolib/src/xmp.cpp glbackend/gl_hwtexture.cpp glbackend/gl_samplers.cpp @@ -844,6 +812,7 @@ set (PCH_SOURCES common/music/i_soundfont.cpp common/music/music_config.cpp common/music/music_midi_base.cpp + common/music/musicstream.cpp ) diff --git a/source/audiolib/include/fx_man.h b/source/audiolib/include/fx_man.h index ad6e9ef12..513e3a5c3 100644 --- a/source/audiolib/include/fx_man.h +++ b/source/audiolib/include/fx_man.h @@ -97,8 +97,6 @@ static FORCE_INLINE int FX_GetReverbDelay(void) { return MV_GetReverbDelay(); } static FORCE_INLINE void FX_SetReverbDelay(int delay) { MV_SetReverbDelay(delay); } static FORCE_INLINE int FX_VoiceAvailable(int priority) { return MV_VoiceAvailable(priority); } static FORCE_INLINE int FX_PauseVoice(int handle, int pause) { return FX_CheckMVErr(MV_PauseVoice(handle, pause)); } -static FORCE_INLINE int FX_GetPosition(int handle, int *position) { return FX_CheckMVErr(MV_GetPosition(handle, position)); } -static FORCE_INLINE int FX_SetPosition(int handle, int position) { return FX_CheckMVErr(MV_SetPosition(handle, position)); } static FORCE_INLINE int FX_EndLooping(int handle) { return FX_CheckMVErr(MV_EndLooping(handle)); } static FORCE_INLINE int FX_SetPan(int handle, int vol, int left, int right) { diff --git a/source/audiolib/include/multivoc.h b/source/audiolib/include/multivoc.h index 59f06b5f9..c4e93c8f6 100644 --- a/source/audiolib/include/multivoc.h +++ b/source/audiolib/include/multivoc.h @@ -40,10 +40,11 @@ typedef enum : char FMT_RAW, FMT_VOC, FMT_WAV, + FMT_SNDFILE, + FMT_ZMUSIC, + // soon to be obsolete. FMT_VORBIS, FMT_FLAC, - FMT_XA, - FMT_XMP, FMT_MAX } wavefmt_t; @@ -109,15 +110,10 @@ decltype(MV_PlayVOC3D) MV_PlayVorbis3D; decltype(MV_PlayVOC) MV_PlayVorbis; decltype(MV_PlayVOC3D) MV_PlayFLAC3D; decltype(MV_PlayVOC) MV_PlayFLAC; -decltype(MV_PlayVOC3D) MV_PlayXA3D; -decltype(MV_PlayVOC) MV_PlayXA; -decltype(MV_PlayVOC3D) MV_PlayXMP3D; -decltype(MV_PlayVOC) MV_PlayXMP; int MV_PlayRAW(char *ptr, uint32_t length, int rate, char *loopstart, char *loopend, int pitchoffset, int vol, int left, int right, int priority, float volume, intptr_t callbackval); -int MV_IdentifyXMP(char const *ptr, uint32_t length); int MV_GetPosition(int handle, int *position); int MV_SetPosition(int handle, int position); void MV_SetVolume(int volume); diff --git a/source/audiolib/src/_multivc.h b/source/audiolib/src/_multivc.h index 87edfc060..0cbf8ed7a 100644 --- a/source/audiolib/src/_multivc.h +++ b/source/audiolib/src/_multivc.h @@ -261,6 +261,7 @@ int MV_GetXMPPosition(VoiceNode *voice); void MV_SetXMPPosition(VoiceNode *voice, int position); void MV_ReleaseVorbisVoice(VoiceNode *voice); +void MV_ReleaseZMusicVoice(VoiceNode* voice); void MV_ReleaseFLACVoice(VoiceNode *voice); void MV_ReleaseXAVoice(VoiceNode *voice); void MV_ReleaseXMPVoice(VoiceNode *voice); diff --git a/source/audiolib/src/flac.cpp b/source/audiolib/src/flac.cpp deleted file mode 100644 index fc8ebc9bc..000000000 --- a/source/audiolib/src/flac.cpp +++ /dev/null @@ -1,695 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -/** - * FLAC source support for MultiVoc - */ - -#include "compat.h" - -#ifdef HAVE_FLAC - -#define FLAC__NO_DLL - -#ifdef __APPLE__ -#include -#else -#include "FLAC/all.h" -#endif - -#include "_multivc.h" -#include "multivoc.h" -#include "pitch.h" -#include "pragmas.h" - -typedef struct -{ - void *ptr; - size_t length; - size_t pos; - - FLAC__StreamDecoder *stream; - FLAC__uint64 sample_pos; - - char *block; - size_t blocksize; - - VoiceNode *owner; -} flac_data; - -// callbacks, round 1 - -static size_t read_flac(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle datasource) -{ - flac_data *flac = (flac_data *)datasource; - size_t nread = 0; - size_t bytes; - - errno = 0; - - if (flac->length == flac->pos) - { - return 0; - } - - for (; nmemb > 0; nmemb--, nread++) - { - bytes = flac->length - flac->pos; - if (size < bytes) - { - bytes = size; - } - - memcpy(ptr, (uint8_t *)flac->ptr + flac->pos, bytes); - flac->pos += bytes; - ptr = (uint8_t *)ptr + bytes; - - if (flac->length == flac->pos) - { - nread++; - break; - } - } - - return nread; -} - -static size_t write_flac(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle datasource) -{ - UNREFERENCED_PARAMETER(ptr); - UNREFERENCED_PARAMETER(size); - UNREFERENCED_PARAMETER(nmemb); - UNREFERENCED_PARAMETER(datasource); - - return 0; -} - -static int seek_flac(FLAC__IOHandle datasource, FLAC__int64 offset, int whence) -{ - flac_data *flac = (flac_data *)datasource; - - switch (whence) - { - case SEEK_SET: flac->pos = 0; break; - case SEEK_CUR: break; - case SEEK_END: flac->pos = flac->length; break; - } - - flac->pos += offset; - - if (flac->pos > flac->length) - { - flac->pos = flac->length; - } - - return 0; -} - -static FLAC__int64 tell_flac(FLAC__IOHandle datasource) -{ - flac_data *flac = (flac_data *)datasource; - - return flac->pos; -} - -static FLAC__int64 length_flac(FLAC__IOHandle datasource) -{ - flac_data *flac = (flac_data *)datasource; - - return flac->length; -} - -static int eof_flac(FLAC__IOHandle datasource) -{ - flac_data *flac = (flac_data *)datasource; - - return (flac->pos == flac->length); -} - -static int close_flac(FLAC__IOHandle datasource) -{ - UNREFERENCED_PARAMETER(datasource); - return 0; -} - -static FLAC__IOCallbacks flac_callbacks = { - read_flac, write_flac, seek_flac, tell_flac, eof_flac, close_flac, -}; - - -// callbacks, round 2 - -FLAC__StreamDecoderReadStatus read_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, - void *client_data) -{ - UNREFERENCED_PARAMETER(decoder); - if (*bytes > 0) - { - *bytes = read_flac(buffer, sizeof(FLAC__byte), *bytes, client_data); - if (errno) - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - else if (*bytes == 0) - return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - else - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - } - else - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; -} - -FLAC__StreamDecoderSeekStatus seek_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, - void *client_data) -{ - UNREFERENCED_PARAMETER(decoder); - if (seek_flac(client_data, absolute_byte_offset, SEEK_SET) < 0) - return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; - else - return FLAC__STREAM_DECODER_SEEK_STATUS_OK; -} - -FLAC__StreamDecoderTellStatus tell_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, - void *client_data) -{ - UNREFERENCED_PARAMETER(decoder); - *absolute_byte_offset = tell_flac(client_data); - return FLAC__STREAM_DECODER_TELL_STATUS_OK; -} - -FLAC__StreamDecoderLengthStatus length_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, - void *client_data) -{ - UNREFERENCED_PARAMETER(decoder); - *stream_length = length_flac(client_data); - return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; -} - -FLAC__bool eof_flac_stream(const FLAC__StreamDecoder *decoder, void *client_data) -{ - UNREFERENCED_PARAMETER(decoder); - return eof_flac(client_data); -} - -FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, - const FLAC__int32 *const ibuffer[], void *client_data) -{ - flac_data *fd = (flac_data *)client_data; - VoiceNode *voice = fd->owner; - FLAC__uint64 samples = frame->header.blocksize; - - UNREFERENCED_PARAMETER(decoder); - - voice->channels = frame->header.channels; - voice->bits = frame->header.bits_per_sample; - voice->SamplingRate = frame->header.sample_rate; - - if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) - fd->sample_pos = frame->header.number.frame_number; - else if (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER) - fd->sample_pos = frame->header.number.sample_number; - - if ((FLAC__uint64)(uintptr_t)voice->LoopEnd > 0 && - fd->sample_pos + samples >= (FLAC__uint64)(uintptr_t)voice->LoopEnd) - { - samples = (FLAC__uint64)(uintptr_t)voice->LoopEnd - fd->sample_pos; - if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart)) - MV_Printf("MV_GetNextFLACBlock FLAC__stream_decoder_seek_absolute: LOOP_START %ul, LOOP_END %ul\n", - (FLAC__uint64)(uintptr_t)voice->LoopStart, (FLAC__uint64)(uintptr_t)voice->LoopEnd); - } - - size_t const size = samples * voice->channels * (voice->bits >> 3); - - voice->position = 0; - voice->BlockLength = 0; - // CODEDUP multivoc.c MV_SetVoicePitch - voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate); - voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale; - MV_SetVoiceMixMode(voice); - - char * block = fd->block; - - if (size > fd->blocksize) - { - block = (char *)Xmalloc(size); - - if (block == nullptr) - return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } - - { - char *obuffer = block; - FLAC__uint64 sample; - uint8_t channel; - - // this loop is adapted from code in ov_read_filter() in vorbisfile.c in libvorbis - for (sample = 0; sample < samples; ++sample) - for (channel = 0; channel < frame->header.channels; ++channel) - { - int8_t byte; - FLAC__int32 val = ibuffer[channel][sample]; - if (val > (1 << (voice->bits - 1)) - 1) - val = (1 << (voice->bits - 1)) - 1; - else if (val < -(1 << (voice->bits - 1))) - val = -(1 << (voice->bits - 1)); - for (byte = 0; byte < voice->bits; byte += 8) *obuffer++ = ((val >> byte) & 0x000000FF); - } - } - - voice->sound = block; - voice->length = samples << 16; - - if (block != fd->block) - { - char * oldblock = fd->block; - fd->block = block; - fd->blocksize = size; - Xfree(oldblock); - } - - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; -} - -void error_flac_stream(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) -{ - // flac_data * fd = (flac_data *) client_data; - UNREFERENCED_PARAMETER(client_data); - UNREFERENCED_PARAMETER(decoder); - MV_Printf("%s\n", FLAC__StreamDecoderErrorStatusString[status]); - // FLAC__stream_decoder_flush(fd->stream); -} - -int MV_GetFLACPosition(VoiceNode *voice) -{ - FLAC__uint64 position = 0; - flac_data *fd = (flac_data *)voice->rawdataptr; - - FLAC__stream_decoder_get_decode_position(fd->stream, &position); - - return position; -} - -void MV_SetFLACPosition(VoiceNode *voice, int position) -{ - flac_data *fd = (flac_data *)voice->rawdataptr; - - FLAC__stream_decoder_seek_absolute(fd->stream, position); -} - -/*--------------------------------------------------------------------- -Function: MV_GetNextFLACBlock - -Controls playback of FLAC data ----------------------------------------------------------------------*/ - -static playbackstatus MV_GetNextFLACBlock(VoiceNode *voice) - -{ - flac_data *fd = (flac_data *)voice->rawdataptr; - FLAC__StreamDecoderState decode_state; - // FLAC__bool decode_status; - - if ((FLAC__uint64)(uintptr_t)voice->LoopEnd > 0 && fd->sample_pos >= (FLAC__uint64)(uintptr_t)voice->LoopEnd) - if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart)) - MV_Printf("MV_GetNextFLACBlock FLAC__stream_decoder_seek_absolute: LOOP_START %ul, LOOP_END %ul\n", - (FLAC__uint64)(uintptr_t)voice->LoopStart, (FLAC__uint64)(uintptr_t)voice->LoopEnd); - - /*decode_status =*/FLAC__stream_decoder_process_single(fd->stream); - decode_state = FLAC__stream_decoder_get_state(fd->stream); - - /* - if (!decode_status) - { - MV_Printf("MV_GetNextFLACBlock: %s\n", FLAC__StreamDecoderStateString[decode_state]); - return NoMoreData; - } - */ - - if (decode_state == FLAC__STREAM_DECODER_SEEK_ERROR) - { - FLAC__stream_decoder_flush(fd->stream); - decode_state = FLAC__stream_decoder_get_state(fd->stream); - } - - if (decode_state == FLAC__STREAM_DECODER_END_OF_STREAM) - { - if (voice->LoopSize > 0) - { - if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart)) - MV_Printf("MV_GetNextFLACBlock FLAC__stream_decoder_seek_absolute: LOOP_START %ul\n", - (FLAC__uint64)(uintptr_t)voice->LoopStart); - } - else - return NoMoreData; - } - -#if 0 - // unnecessary: duplicated in write_flac_stream() - voice->channels = FLAC__stream_decoder_get_channels(fd->stream); - voice->bits = FLAC__stream_decoder_get_bits_per_sample(fd->stream); - voice->SamplingRate = FLAC__stream_decoder_get_sample_rate(fd->stream); - // CODEDUP multivoc.c MV_SetVoicePitch - voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; - voice->FixedPointBufferSize = ( voice->RateScale * MV_MIXBUFFERSIZE ) - voice->RateScale; - MV_SetVoiceMixMode( voice ); -#endif - - return KeepPlaying; -} - - -/*--------------------------------------------------------------------- -Function: MV_PlayFLAC3D - -Begin playback of sound data at specified angle and distance -from listener. ----------------------------------------------------------------------*/ - -int MV_PlayFLAC3D(char *ptr, uint32_t length, int loophow, int pitchoffset, int angle, int distance, int priority, float volume, intptr_t callbackval) -{ - int left; - int right; - int mid; - int vol; - int status; - - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - if (distance < 0) - { - distance = -distance; - angle += MV_NUMPANPOSITIONS / 2; - } - - vol = MIX_VOLUME(distance); - - // Ensure angle is within 0 - 127 - angle &= MV_MAXPANPOSITION; - - left = MV_PanTable[angle][vol].left; - right = MV_PanTable[angle][vol].right; - mid = max(0, 255 - distance); - - status = MV_PlayFLAC(ptr, length, loophow, -1, pitchoffset, mid, left, right, priority, volume, callbackval); - - return status; -} - - -/*--------------------------------------------------------------------- -Function: MV_PlayFLAC - -Begin playback of sound data with the given sound levels and -priority. ----------------------------------------------------------------------*/ - -int MV_PlayFLAC(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, int left, int right, int priority, float volume, intptr_t callbackval) -{ - VoiceNode *voice; - flac_data *fd = 0; - FLAC__Metadata_Chain *metadata_chain; - - UNREFERENCED_PARAMETER(loopend); - - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - fd = (flac_data *)Xcalloc(1, sizeof(flac_data)); - if (!fd) - return MV_SetErrorCode(MV_InvalidFile); - - fd->ptr = ptr; - fd->pos = 0; - fd->blocksize = 0; - fd->length = length; - - fd->block = nullptr; - - fd->stream = FLAC__stream_decoder_new(); - fd->sample_pos = 0; - - FLAC__stream_decoder_set_metadata_ignore_all(fd->stream); - - if (FLAC__stream_decoder_init_stream(fd->stream, read_flac_stream, seek_flac_stream, tell_flac_stream, - length_flac_stream, eof_flac_stream, write_flac_stream, - /*metadata_flac_stream*/ nullptr, error_flac_stream, - (void *)fd) != FLAC__STREAM_DECODER_INIT_STATUS_OK) - { - Xfree(fd); - MV_Printf("MV_PlayFLAC: %s\n", FLAC__stream_decoder_get_resolved_state_string(fd->stream)); - return MV_SetErrorCode(MV_InvalidFile); - } - - // Request a voice from the voice pool - voice = MV_AllocVoice(priority); - if (voice == nullptr) - { - FLAC__stream_decoder_finish(fd->stream); - FLAC__stream_decoder_delete(fd->stream); - Xfree(fd); - return MV_SetErrorCode(MV_NoVoices); - } - - fd->owner = voice; - - voice->wavetype = FMT_FLAC; - voice->rawdataptr = (void *)fd; - voice->GetSound = MV_GetNextFLACBlock; - voice->NextBlock = fd->block; - voice->LoopCount = 0; - voice->BlockLength = 0; - voice->PitchScale = PITCH_GetScale(pitchoffset); - voice->next = nullptr; - voice->prev = nullptr; - voice->priority = priority; - voice->callbackval = callbackval; - - voice->Paused = FALSE; - - voice->LoopStart = 0; - voice->LoopEnd = 0; - voice->LoopSize = (loopstart >= 0 ? 1 : 0); - - // parse metadata - // loop parsing designed with multiple repetitions in mind - // In retrospect, it may be possible to MV_GetVorbisCommentLoops(voice, (vorbis_comment *) - // &tags->data.vorbis_comment) - // but libvorbisfile may be confused by the signedness of char* vs FLAC__byte* and this code does not depend on - // HAVE_VORBIS. - metadata_chain = FLAC__metadata_chain_new(); - if (metadata_chain != nullptr) - { - if (FLAC__metadata_chain_read_with_callbacks(metadata_chain, fd, flac_callbacks)) - { - FLAC__Metadata_Iterator *metadata_iterator = FLAC__metadata_iterator_new(); - if (metadata_iterator != nullptr) - { - char *vc_loopstart = nullptr; - char *vc_loopend = nullptr; - char *vc_looplength = nullptr; - - FLAC__metadata_iterator_init(metadata_iterator, metadata_chain); - - do - { - FLAC__StreamMetadata *tags = FLAC__metadata_iterator_get_block(metadata_iterator); - - if (tags->type == FLAC__METADATA_TYPE_STREAMINFO) - { - const FLAC__StreamMetadata_StreamInfo *info = &tags->data.stream_info; - - if (info->channels != 1 && info->channels != 2) - { - FLAC__metadata_object_delete(tags); - FLAC__metadata_iterator_delete(metadata_iterator); - // FLAC__metadata_chain_delete(metadata_chain); - FLAC__stream_decoder_finish(fd->stream); - FLAC__stream_decoder_delete(fd->stream); - Xfree(fd); - return MV_SetErrorCode(MV_InvalidFile); - } - - voice->channels = info->channels; - voice->bits = info->bits_per_sample; - voice->SamplingRate = info->sample_rate; - } - - // load loop tags from metadata - if (tags->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) - { - FLAC__uint32 comment; - for (comment = 0; comment < tags->data.vorbis_comment.num_comments; ++comment) - { - const char *entry = (const char *)tags->data.vorbis_comment.comments[comment].entry; - if (entry != nullptr && entry[0] != '\0') - { - const char *value = strchr(entry, '='); - const size_t field = value - entry; - value += 1; - - for (int t = 0; t < loopStartTagCount && vc_loopstart == nullptr; ++t) - { - char const * const tag = loopStartTags[t]; - if (field == strlen(tag) && Bstrncasecmp(entry, tag, field) == 0) - vc_loopstart = Xstrdup(value); - } - - for (int t = 0; t < loopEndTagCount && vc_loopend == nullptr; ++t) - { - char const * const tag = loopEndTags[t]; - if (field == strlen(tag) && Bstrncasecmp(entry, tag, field) == 0) - vc_loopend = Xstrdup(value); - } - - for (int t = 0; t < loopLengthTagCount && vc_looplength == nullptr; ++t) - { - char const * const tag = loopLengthTags[t]; - if (field == strlen(tag) && Bstrncasecmp(entry, tag, field) == 0) - vc_looplength = Xstrdup(value); - } - } - } - } - - FLAC__metadata_object_delete( - tags); // If it were not for this, I would assign pointers instead of strdup(). - } while (FLAC__metadata_iterator_next(metadata_iterator)); - - if (vc_loopstart != nullptr) - { - { - const FLAC__int64 flac_loopstart = atol(vc_loopstart); - if (flac_loopstart >= 0) // a loop starting at 0 is valid - { - voice->LoopStart = (const char *)(intptr_t)flac_loopstart; - voice->LoopSize = 1; - } - } - free(vc_loopstart); - } - if (vc_loopend != nullptr) - { - if (voice->LoopSize > 0) - { - const FLAC__int64 flac_loopend = atol(vc_loopend); - if (flac_loopend > 0) // a loop ending at 0 is invalid - voice->LoopEnd = (const char *)(intptr_t)flac_loopend; - } - free(vc_loopend); - } - if (vc_looplength != nullptr) - { - if (voice->LoopSize > 0 && voice->LoopEnd == 0) - { - const FLAC__int64 flac_looplength = atol(vc_looplength); - if (flac_looplength > 0) // a loop of length 0 is invalid - voice->LoopEnd = (const char *)((intptr_t)flac_looplength + (intptr_t)voice->LoopStart); - } - free(vc_looplength); - } - - FLAC__metadata_iterator_delete(metadata_iterator); - } - else - MV_Printf("Error allocating FLAC__Metadata_Iterator!\n"); - } - else - MV_Printf("%s\n", FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(metadata_chain)]); - - // FLAC__metadata_chain_delete(metadata_chain); // when run with GDB, this throws SIGTRAP about freed heap - // memory being modified - } - else - MV_Printf("Error allocating FLAC__Metadata_Chain!\n"); - - // CODEDUP multivoc.c MV_SetVoicePitch - voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate); - voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale; - MV_SetVoiceMixMode(voice); - - MV_SetVoiceVolume(voice, vol, left, right, volume); - MV_PlayVoice(voice); - - return voice->handle; -} - - -void MV_ReleaseFLACVoice(VoiceNode *voice) -{ - flac_data *fd = (flac_data *)voice->rawdataptr; - - if (voice->wavetype != FMT_FLAC) - { - return; - } - - voice->rawdataptr = 0; - if (fd->stream != nullptr) - { - auto stream = fd->stream; - fd->stream = nullptr; - FLAC__stream_decoder_finish(stream); - FLAC__stream_decoder_delete(stream); - } - auto block = fd->block; - voice->length = 0; - voice->sound = nullptr; - fd->block = nullptr; - Xfree(block); - Xfree(fd); -} -#else -#include "_multivc.h" - -int MV_PlayFLAC(char *ptr, uint32_t ptrlength, int loopstart, int loopend, int pitchoffset, - int vol, int left, int right, int priority, float volume, intptr_t callbackval) -{ - UNREFERENCED_PARAMETER(ptr); - UNREFERENCED_PARAMETER(ptrlength); - UNREFERENCED_PARAMETER(loopstart); - UNREFERENCED_PARAMETER(loopend); - UNREFERENCED_PARAMETER(pitchoffset); - UNREFERENCED_PARAMETER(vol); - UNREFERENCED_PARAMETER(left); - UNREFERENCED_PARAMETER(right); - UNREFERENCED_PARAMETER(priority); - UNREFERENCED_PARAMETER(volume); - UNREFERENCED_PARAMETER(callbackval); - - MV_Printf("MV_PlayFLAC: FLAC support not included in this binary.\n"); - return -1; -} - -int MV_PlayFLAC3D(char *ptr, uint32_t ptrlength, int loophow, int pitchoffset, int angle, - int distance, int priority, float volume, intptr_t callbackval) -{ - UNREFERENCED_PARAMETER(ptr); - UNREFERENCED_PARAMETER(ptrlength); - UNREFERENCED_PARAMETER(loophow); - UNREFERENCED_PARAMETER(pitchoffset); - UNREFERENCED_PARAMETER(angle); - UNREFERENCED_PARAMETER(distance); - UNREFERENCED_PARAMETER(priority); - UNREFERENCED_PARAMETER(volume); - UNREFERENCED_PARAMETER(callbackval); - - MV_Printf("MV_PlayFLAC: FLAC support not included in this binary.\n"); - return -1; -} -#endif // HAVE_FLAC diff --git a/source/audiolib/src/fx_man.cpp b/source/audiolib/src/fx_man.cpp index 97366a585..2d3d10799 100644 --- a/source/audiolib/src/fx_man.cpp +++ b/source/audiolib/src/fx_man.cpp @@ -135,20 +135,12 @@ static wavefmt_t FX_DetectFormat(char const * const ptr, uint32_t length) case 'R' + ('I' << 8) + ('F' << 16) + ('F' << 24): // RIFF switch (B_LITTLE32(*(int const *)(ptr + 8))) { - case 'C' + ('D' << 8) + ('X' << 16) + ('A' << 24): // CDXA - fmt = FMT_XA; - break; case 'W' + ('A' << 8) + ('V' << 16) + ('E' << 24): // WAVE fmt = FMT_WAV; break; } break; - case 'f' + ('L' << 8) + ('a' << 16) + ('C' << 24): // fLaC - fmt = FMT_FLAC; - break; default: - if (MV_IdentifyXMP(ptr, length)) - fmt = FMT_XMP; break; } @@ -159,9 +151,9 @@ int FX_Play(char *ptr, uint32_t ptrlength, int loopstart, int loopend, int pitch int vol, int left, int right, int priority, float volume, intptr_t callbackval) { static constexpr decltype(MV_PlayVOC) *func[] = - { nullptr, nullptr, MV_PlayVOC, MV_PlayWAV, MV_PlayVorbis, MV_PlayFLAC, MV_PlayXA, MV_PlayXMP }; + { nullptr, nullptr, MV_PlayVOC, MV_PlayWAV, nullptr, nullptr, MV_PlayVorbis, nullptr, nullptr, nullptr }; - EDUKE32_STATIC_ASSERT(FMT_MAX == ARRAY_SIZE(func)); + //EDUKE32_STATIC_ASSERT(FMT_MAX == ARRAY_SIZE(func)); wavefmt_t const fmt = FX_DetectFormat(ptr, ptrlength); @@ -181,9 +173,9 @@ int FX_Play3D(char *ptr, uint32_t ptrlength, int loophow, int pitchoffset, int a int priority, float volume, intptr_t callbackval) { static constexpr decltype(MV_PlayVOC3D) *func[] = - { nullptr, nullptr, MV_PlayVOC3D, MV_PlayWAV3D, MV_PlayVorbis3D, MV_PlayFLAC3D, MV_PlayXA3D, MV_PlayXMP3D }; + { nullptr, nullptr, MV_PlayVOC3D, MV_PlayWAV3D, nullptr, nullptr, MV_PlayVorbis3D, nullptr, nullptr, nullptr }; - EDUKE32_STATIC_ASSERT(FMT_MAX == ARRAY_SIZE(func)); + //EDUKE32_STATIC_ASSERT(FMT_MAX == ARRAY_SIZE(func)); wavefmt_t const fmt = FX_DetectFormat(ptr, ptrlength); diff --git a/source/audiolib/src/multivoc.cpp b/source/audiolib/src/multivoc.cpp index 7ff4da3c7..c0d04fe2c 100644 --- a/source/audiolib/src/multivoc.cpp +++ b/source/audiolib/src/multivoc.cpp @@ -170,16 +170,8 @@ static void MV_CleanupVoice(VoiceNode *voice) switch (voice->wavetype) { -#ifdef HAVE_VORBIS case FMT_VORBIS: MV_ReleaseVorbisVoice(voice); break; -#endif -#ifdef HAVE_FLAC - case FMT_FLAC: MV_ReleaseFLACVoice(voice); break; -#endif - case FMT_XA: MV_ReleaseXAVoice(voice); break; -#ifdef HAVE_XMP - case FMT_XMP: MV_ReleaseXMPVoice(voice); break; -#endif + case FMT_ZMUSIC: MV_ReleaseZMusicVoice(voice); break; default: break; } @@ -571,62 +563,6 @@ int MV_PauseVoice(int handle, int pause) return MV_Ok; } -int MV_GetPosition(int handle, int *position) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - switch (voice->wavetype) - { -#ifdef HAVE_VORBIS - case FMT_VORBIS: *position = MV_GetVorbisPosition(voice); break; -#endif -#ifdef HAVE_FLAC - case FMT_FLAC: *position = MV_GetFLACPosition(voice); break; -#endif - case FMT_XA: *position = MV_GetXAPosition(voice); - default: - break; -#ifdef HAVE_XMP - case FMT_XMP: *position = MV_GetXMPPosition(voice); break; -#endif - } - - MV_EndService(); - - return MV_Ok; -} - -int MV_SetPosition(int handle, int position) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - switch (voice->wavetype) - { -#ifdef HAVE_VORBIS - case FMT_VORBIS: MV_SetVorbisPosition(voice, position); break; -#endif -#ifdef HAVE_FLAC - case FMT_FLAC: MV_SetFLACPosition(voice, position); break; -#endif - case FMT_XA: MV_SetXAPosition(voice, position); - default: - break; -#ifdef HAVE_XMP - case FMT_XMP: MV_SetXMPPosition(voice, position); break; -#endif - } - - MV_EndService(); - - return MV_Ok; -} - int MV_EndLooping(int handle) { VoiceNode *voice = MV_BeginService(handle); diff --git a/source/audiolib/src/xa.cpp b/source/audiolib/src/xa.cpp deleted file mode 100644 index 0ed7815c0..000000000 --- a/source/audiolib/src/xa.cpp +++ /dev/null @@ -1,481 +0,0 @@ - -/** - * PlayStation XA (ADPCM) source support for MultiVoc - * Adapted and remixed from superxa2wav - */ - -#include "_multivc.h" -#include "compat.h" -#include "multivoc.h" -#include "pitch.h" -#include "pragmas.h" - -//#define NO_XA_HEADER - -#define USE_FXD 1 - -#define kNumOfSamples 224 -#define kNumOfSGs 18 -#define TTYWidth 80 - -#define kBufSize (kNumOfSGs*kNumOfSamples*(16/8)) -#define kSamplesMono (kNumOfSGs*kNumOfSamples) -#define kSamplesStereo (kNumOfSGs*kNumOfSamples/2) - -/* ADPCM */ -#define XA_DATA_START (0x44-48) - -#define FXD_FxdToPCM(dt) (max(min((int16_t)((dt)>>16), 32767), -32768)) -#define DblToPCM(dt) (int16_t)(max(min((dt), 32767), -32768)) - -#if USE_FXD -#define FXD_FxdToPcm16(dt) (max(min((dt)/2, 32767), -32768)) -#define FXD_Pcm16ToFxd(dt) ((int)dt*2) -#endif - -typedef struct { - void * ptr; - size_t length; - size_t pos; - -#if USE_FXD - int t1, t2; - int t1_x, t2_x; -#else - double t1, t2; - double t1_x, t2_x; -#endif - - int8_t block[kBufSize]; - - VoiceNode *owner; -} xa_data; - -typedef int8_t SoundGroup[128]; - -typedef struct XASector { - int8_t sectorFiller[48]; - SoundGroup SoundGroups[18]; -} XASector; - -#if USE_FXD -static int K0[4] = { - 0x00000000, - 0x0000F000, - 0x0001CC00, - 0x00018800, -}; -static int K1[4] = { - 0x00000000, - 0x00000000, - (int)0xFFFF3000u, - (int)0xFFFF2400u, -}; -#else -static double K0[4] = { - 0.0, - 0.9375, - 1.796875, - 1.53125 -}; -static double K1[4] = { - 0.0, - 0.0, - -0.8125, - -0.859375 -}; -#endif - - -#if USE_FXD -static int FXD_FixMul(int a, int b) -{ - int high_a, low_a, high_b, low_b; - int hahb, halb, lahb; - uint32_t lalb; - int ret; - - high_a = a >> 16; - low_a = a & 0x0000FFFF; - high_b = b >> 16; - low_b = b & 0x0000FFFF; - - hahb = (high_a * high_b) << 16; - halb = high_a * low_b; - lahb = low_a * high_b; - lalb = (uint32_t)(low_a * low_b) >> 16; - - ret = hahb + halb + lahb + lalb; - - return ret; -} -#endif - - - -static int8_t getSoundData(int8_t *buf, int unit, int sample) -{ - int8_t ret; - int8_t *p; - int offset, shift; - - p = buf; - shift = (unit%2) * 4; - - offset = 16 + (unit / 2) + (sample * 4); - p += offset; - - ret = (*p >> shift) & 0x0F; - - if (ret > 7) { - ret -= 16; - } - return ret; -} - -static int8_t getFilter(const int8_t *buf, int unit) -{ - return (*(buf + 4 + unit) >> 4) & 0x03; -} - - -static int8_t getRange(const int8_t *buf, int unit) -{ - return *(buf + 4 + unit) & 0x0F; -} - - -static void decodeSoundSectMono(XASector *ssct, xa_data * xad) -{ - size_t count = 0; - int8_t snddat, filt, range; - int16_t decoded; - int unit, sample; - int sndgrp; -#if USE_FXD - int tmp2, tmp3, tmp4, tmp5; -#else - double tmp2, tmp3, tmp4, tmp5; -#endif - int8_t decodeBuf[kBufSize]; - - for (sndgrp = 0; sndgrp < kNumOfSGs; sndgrp++) - { - for (unit = 0; unit < 8; unit++) - { - range = getRange(ssct->SoundGroups[sndgrp], unit); - filt = getFilter(ssct->SoundGroups[sndgrp], unit); - for (sample = 0; sample < 28; sample++) - { - snddat = getSoundData(ssct->SoundGroups[sndgrp], unit, sample); -#if USE_FXD - tmp2 = (int)(snddat) << (12 - range); - tmp3 = FXD_Pcm16ToFxd(tmp2); - tmp4 = FXD_FixMul(K0[filt], xad->t1); - tmp5 = FXD_FixMul(K1[filt], xad->t2); - xad->t2 = xad->t1; - xad->t1 = tmp3 + tmp4 + tmp5; - decoded = FXD_FxdToPcm16(xad->t1); -#else - tmp2 = (double)(1 << (12 - range)); - tmp3 = (double)snddat * tmp2; - tmp4 = xad->t1 * K0[filt]; - tmp5 = xad->t2 * K1[filt]; - xad->t2 = xad->t1; - xad->t1 = tmp3 + tmp4 + tmp5; - decoded = DblToPCM(xad->t1); -#endif - decodeBuf[count++] = (int8_t) ((uint16_t)decoded & 0x00FF); - decodeBuf[count++] = (int8_t)(((uint16_t)decoded & 0xFF00) >> 8); - } - } - } - - memcpy(xad->block, decodeBuf, kBufSize); -} - -static void decodeSoundSectStereo(XASector *ssct, xa_data * xad) -{ - size_t count = 0; - int8_t snddat, filt, range; - int8_t filt1, range1; - int16_t decoded; - int unit, sample; - int sndgrp; -#if USE_FXD - int tmp2, tmp3, tmp4, tmp5; -#else - double tmp2, tmp3, tmp4, tmp5; -#endif - int8_t decodeBuf[kBufSize]; - - for (sndgrp = 0; sndgrp < kNumOfSGs; sndgrp++) - { - for (unit = 0; unit < 8; unit+= 2) - { - range = getRange(ssct->SoundGroups[sndgrp], unit); - filt = getFilter(ssct->SoundGroups[sndgrp], unit); - range1 = getRange(ssct->SoundGroups[sndgrp], unit+1); - filt1 = getFilter(ssct->SoundGroups[sndgrp], unit+1); - - for (sample = 0; sample < 28; sample++) - { - // Channel 1 - snddat = getSoundData(ssct->SoundGroups[sndgrp], unit, sample); -#if USE_FXD - tmp2 = (int)(snddat) << (12 - range); - tmp3 = FXD_Pcm16ToFxd(tmp2); - tmp4 = FXD_FixMul(K0[filt], xad->t1); - tmp5 = FXD_FixMul(K1[filt], xad->t2); - xad->t2 = xad->t1; - xad->t1 = tmp3 + tmp4 + tmp5; - decoded = FXD_FxdToPcm16(xad->t1); -#else - tmp2 = (double)(1 << (12 - range)); - tmp3 = (double)snddat * tmp2; - tmp4 = xad->t1 * K0[filt]; - tmp5 = xad->t2 * K1[filt]; - xad->t2 = xad->t1; - xad->t1 = tmp3 + tmp4 + tmp5; - decoded = DblToPCM(xad->t1); -#endif - decodeBuf[count++] = (int8_t) ((uint16_t)decoded & 0x00FF); - decodeBuf[count++] = (int8_t)(((uint16_t)decoded & 0xFF00) >> 8); - - // Channel 2 - snddat = getSoundData(ssct->SoundGroups[sndgrp], unit+1, sample); -#if USE_FXD - tmp2 = (int)(snddat) << (12 - range1); - tmp3 = FXD_Pcm16ToFxd(tmp2); - tmp4 = FXD_FixMul(K0[filt1], xad->t1_x); - tmp5 = FXD_FixMul(K1[filt1], xad->t2_x); - xad->t2_x = xad->t1_x; - xad->t1_x = tmp3 + tmp4 + tmp5; - decoded = FXD_FxdToPcm16(xad->t1_x); -#else - tmp2 = (double)(1 << (12 - range1)); - tmp3 = (double)snddat * tmp2; - tmp4 = xad->t1_x * K0[filt1]; - tmp5 = xad->t2_x * K1[filt1]; - xad->t2_x = xad->t1_x; - xad->t1_x = tmp3 + tmp4 + tmp5; - decoded = DblToPCM(xad->t1_x); -#endif - decodeBuf[count++] = (int8_t) ((uint16_t)decoded & 0x00FF); - decodeBuf[count++] = (int8_t)(((uint16_t)decoded & 0xFF00) >> 8); - } - } - } - - memcpy(xad->block, decodeBuf, kBufSize); -} - -int MV_GetXAPosition(VoiceNode *voice) -{ - auto xad = (xa_data *) voice->rawdataptr; - return xad->pos; -} - -void MV_SetXAPosition(VoiceNode *voice, int position) -{ - auto xad = (xa_data *) voice->rawdataptr; - - if (position < XA_DATA_START || (size_t)position >= xad->length) - { - position = XA_DATA_START; - xad->t1 = xad->t2 = xad->t1_x = xad->t2_x = 0; - } - - xad->pos = position; -} - -/*--------------------------------------------------------------------- -Function: MV_GetNextXABlock - -Controls playback of XA data ----------------------------------------------------------------------*/ - -static playbackstatus MV_GetNextXABlock -( - VoiceNode *voice - ) -{ - auto xad = (xa_data *) voice->rawdataptr; - XASector ssct; - int coding; - - do - { - size_t bytes = xad->length - xad->pos; - - if (sizeof(XASector) < bytes) - bytes = sizeof(XASector); - - memcpy(&ssct, (int8_t *)xad->ptr + xad->pos, bytes); - xad->pos += bytes; - } -#define SUBMODE_REAL_TIME_SECTOR (1 << 6) -#define SUBMODE_FORM (1 << 5) -#define SUBMODE_AUDIO_DATA (1 << 2) - while (ssct.sectorFiller[46] != (SUBMODE_REAL_TIME_SECTOR | SUBMODE_FORM | SUBMODE_AUDIO_DATA)); - - coding = ssct.sectorFiller[47]; - - voice->channels = (coding & 3) + 1; - voice->SamplingRate = (((coding >> 2) & 3) == 1) ? 18900 : 37800; - - // CODEDUP multivoc.c MV_SetVoicePitch - voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate); - voice->FixedPointBufferSize = ( voice->RateScale * MV_MIXBUFFERSIZE ) - voice->RateScale; - MV_SetVoiceMixMode( voice ); - - uint32_t samples; - - if (voice->channels == 2) - { - decodeSoundSectStereo(&ssct, xad); - samples = kSamplesStereo; - } - else - { - decodeSoundSectMono(&ssct, xad); - samples = kSamplesMono; - } - - voice->sound = (char *)xad->block; - voice->length = samples << 16; - voice->position = 0; - voice->BlockLength = 0; - - if (xad->length == xad->pos) - { - if (voice->LoopSize > 0) - { - xad->pos = XA_DATA_START; - xad->t1 = xad->t2 = xad->t1_x = xad->t2_x = 0; - } - else - return NoMoreData; - } - - return KeepPlaying; -} - - -/*--------------------------------------------------------------------- -Function: MV_PlayXA3D - -Begin playback of sound data at specified angle and distance -from listener. ----------------------------------------------------------------------*/ - -int MV_PlayXA3D(char *ptr, uint32_t length, int loophow, int pitchoffset, int angle, int distance, int priority, float volume, - intptr_t callbackval) -{ - int left; - int right; - int mid; - int vol; - int status; - - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - if (distance < 0) - { - distance = -distance; - angle += MV_NUMPANPOSITIONS / 2; - } - - vol = MIX_VOLUME(distance); - - // Ensure angle is within 0 - 127 - angle &= MV_MAXPANPOSITION; - - left = MV_PanTable[angle][vol].left; - right = MV_PanTable[angle][vol].right; - mid = max(0, 255 - distance); - - status = MV_PlayXA(ptr, length, loophow, -1, pitchoffset, mid, left, right, priority, volume, callbackval); - - return status; -} - - -/*--------------------------------------------------------------------- -Function: MV_PlayXA - -Begin playback of sound data with the given sound levels and -priority. ----------------------------------------------------------------------*/ - -int MV_PlayXA(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, int left, int right, - int priority, float volume, intptr_t callbackval) -{ - VoiceNode *voice; - xa_data * xad = 0; - - UNREFERENCED_PARAMETER(loopend); - - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - xad = (xa_data *) Xcalloc( 1, sizeof(xa_data) ); - if (!xad) - return MV_SetErrorCode(MV_InvalidFile); - - xad->ptr = ptr; - xad->pos = XA_DATA_START; - xad->t1 = xad->t2 = xad->t1_x = xad->t2_x = 0; - xad->length = length; - - // Request a voice from the voice pool - voice = MV_AllocVoice(priority); - if (voice == nullptr) - { - Xfree(xad); - return MV_SetErrorCode(MV_NoVoices); - } - - xad->owner = voice; - - voice->wavetype = FMT_XA; - voice->rawdataptr = (void*)xad; - voice->GetSound = MV_GetNextXABlock; - voice->NextBlock = (char *)xad->block; - voice->LoopCount = 0; - voice->BlockLength = 0; - voice->PitchScale = PITCH_GetScale( pitchoffset ); - voice->next = nullptr; - voice->prev = nullptr; - voice->priority = priority; - voice->callbackval = callbackval; - - voice->bits = 16; - - voice->Paused = FALSE; - - voice->LoopStart = 0; - voice->LoopEnd = 0; - voice->LoopSize = (loopstart >= 0 ? 1 : 0); - - MV_SetVoiceVolume( voice, vol, left, right, volume ); - MV_PlayVoice( voice ); - - return voice->handle; -} - - -void MV_ReleaseXAVoice( VoiceNode * voice ) -{ - auto xad = (xa_data *) voice->rawdataptr; - - if (voice->wavetype != FMT_XA) { - return; - } - - voice->rawdataptr = 0; - voice->length = 0; - voice->sound = nullptr; - Xfree(xad); -} diff --git a/source/audiolib/src/xmp.cpp b/source/audiolib/src/xmp.cpp deleted file mode 100644 index 80c13156f..000000000 --- a/source/audiolib/src/xmp.cpp +++ /dev/null @@ -1,333 +0,0 @@ - -#include "compat.h" - -#ifdef HAVE_XMP - -#include "_multivc.h" -#include "multivoc.h" -#include "pitch.h" -#include "pragmas.h" - -#define BUILDING_STATIC -#include "libxmp-lite/xmp.h" - -typedef struct { - void * ptr; - VoiceNode *owner; - size_t length; - xmp_context context; - int time; -} xmp_data; - -int MV_GetXMPPosition(VoiceNode *voice) -{ - auto xmpd = (xmp_data *)voice->rawdataptr; - return xmpd->time; -} - -void MV_SetXMPPosition(VoiceNode *voice, int position) -{ - auto xmpd = (xmp_data *)voice->rawdataptr; - xmp_seek_time(xmpd->context, position); -} - -static playbackstatus MV_GetNextXMPBlock(VoiceNode *voice) -{ - auto xmpd = (xmp_data *)voice->rawdataptr; - struct xmp_frame_info mi; - - if (xmp_play_frame(xmpd->context) != 0) - { - if (voice->LoopSize > 0) - { - xmp_restart_module(xmpd->context); - if (xmp_play_frame(xmpd->context) != 0) - return NoMoreData; - } - else - return NoMoreData; - } - - xmp_get_frame_info(xmpd->context, &mi); - - xmpd->time = mi.time; - - uint32_t const samples = mi.buffer_size / (2 * (16/8)); // since 2-channel, 16-bit is hardcoded - // uint32_t const samples = mi.buffer_size / (voice->channels * (voice->bits / 8)); - - voice->sound = (char const *)mi.buffer; - voice->length = samples << 16; - voice->position = 0; - voice->BlockLength = 0; - - MV_SetVoiceMixMode(voice); - - return KeepPlaying; -} - -int MV_PlayXMP3D(char *ptr, uint32_t length, int loophow, int pitchoffset, int angle, int distance, int priority, float volume, intptr_t callbackval) -{ - int left; - int right; - int mid; - int vol; - int status; - - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - if (distance < 0) - { - distance = -distance; - angle += MV_NUMPANPOSITIONS / 2; - } - - vol = MIX_VOLUME(distance); - - // Ensure angle is within 0 - 127 - angle &= MV_MAXPANPOSITION; - - left = MV_PanTable[angle][vol].left; - right = MV_PanTable[angle][vol].right; - mid = max( 0, 255 - distance ); - - status = MV_PlayXMP(ptr, length, loophow, -1, pitchoffset, mid, left, right, priority, volume, callbackval); - - return status; -} - -int MV_PlayXMP(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, int left, int right, int priority, float volume, intptr_t callbackval) -{ - VoiceNode *voice; - xmp_data * xmpd = 0; - int retval; - - UNREFERENCED_PARAMETER(loopend); - - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - xmpd = (xmp_data *)Xcalloc(1, sizeof(xmp_data)); - if (!xmpd) - return MV_SetErrorCode(MV_InvalidFile); - - xmpd->ptr = ptr; - xmpd->length = length; - - if ((xmpd->context = xmp_create_context()) == nullptr) - { - Xfree(xmpd); - return MV_SetErrorCode(MV_InvalidFile); - } - - if ((retval = xmp_load_module_from_memory(xmpd->context, ptr, length)) != 0) - { - Xfree(xmpd); - MV_Printf("MV_PlayXMP: xmp_load_module_from_memory failed (%i)\n", retval); - return MV_SetErrorCode(MV_InvalidFile); - } - - // Request a voice from the voice pool - voice = MV_AllocVoice(priority); - if (voice == nullptr) - { - xmp_release_module(xmpd->context); - xmp_free_context(xmpd->context); - Xfree(xmpd); - return MV_SetErrorCode(MV_NoVoices); - } - - xmpd->owner = voice; - - voice->length = 0; - voice->sound = 0; - - voice->wavetype = FMT_XMP; - voice->rawdataptr = (void*)xmpd; - voice->GetSound = MV_GetNextXMPBlock; - voice->LoopCount = 0; - voice->BlockLength = 0; - voice->PitchScale = PITCH_GetScale(pitchoffset); - voice->next = nullptr; - voice->prev = nullptr; - voice->priority = priority; - voice->callbackval = callbackval; - - voice->bits = 16; - voice->channels = 2; - voice->SamplingRate = MV_MixRate; - - voice->Paused = FALSE; - - voice->LoopStart = 0; - voice->LoopEnd = 0; - voice->LoopSize = loopstart >= 0 ? 1 : 0; - - xmp_start_player(xmpd->context, MV_MixRate, 0); - xmp_set_player(xmpd->context, XMP_PLAYER_INTERP, XMP_INTERP_SPLINE); - - // CODEDUP multivoc.c MV_SetVoicePitch - voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate); - voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale; - MV_SetVoiceMixMode(voice); - - MV_SetVoiceVolume(voice, vol, left, right, volume); - MV_PlayVoice(voice); - - return voice->handle; -} - -void MV_ReleaseXMPVoice(VoiceNode * voice) -{ - auto xmpd = (xmp_data *) voice->rawdataptr; - - if (voice->wavetype != FMT_XMP) - return; - - voice->rawdataptr = 0; - voice->length = 0; - voice->sound = nullptr; - - xmp_end_player(xmpd->context); - xmp_release_module(xmpd->context); - xmp_free_context(xmpd->context); - Xfree(xmpd); -} - -#else - -#include "_multivc.h" - -static char const NoXMP[] = "MV_PlayXMP: libxmp-lite support not included in this binary.\n"; - -int MV_PlayXMP(char *ptr, uint32_t ptrlength, int loopstart, int loopend, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval) -{ - UNREFERENCED_PARAMETER(ptr); - UNREFERENCED_PARAMETER(ptrlength); - UNREFERENCED_PARAMETER(loopstart); - UNREFERENCED_PARAMETER(loopend); - UNREFERENCED_PARAMETER(pitchoffset); - UNREFERENCED_PARAMETER(vol); - UNREFERENCED_PARAMETER(left); - UNREFERENCED_PARAMETER(right); - UNREFERENCED_PARAMETER(priority); - UNREFERENCED_PARAMETER(volume); - UNREFERENCED_PARAMETER(callbackval); - - MV_Printf(NoXMP); - return -1; -} - -int MV_PlayXMP3D(char *ptr, uint32_t ptrlength, int loophow, int pitchoffset, int angle, - int distance, int priority, float volume, intptr_t callbackval) -{ - UNREFERENCED_PARAMETER(ptr); - UNREFERENCED_PARAMETER(ptrlength); - UNREFERENCED_PARAMETER(loophow); - UNREFERENCED_PARAMETER(pitchoffset); - UNREFERENCED_PARAMETER(angle); - UNREFERENCED_PARAMETER(distance); - UNREFERENCED_PARAMETER(priority); - UNREFERENCED_PARAMETER(volume); - UNREFERENCED_PARAMETER(callbackval); - - MV_Printf(NoXMP); - return -1; -} - -#endif - -// KEEPINSYNC libxmp-lite/src/*_load.c - -static int it_test_memory(char const *ptr, uint32_t ptrlength) -{ - static char const it_magic[] = "IMPM"; - - if (ptrlength < sizeof(it_magic)-1 || - memcmp(ptr, it_magic, sizeof(it_magic)-1)) - return -1; - - return 0; -} - -static int mod_test_memory(char const *ptr, uint32_t ptrlength) -{ - if (ptrlength < 1084) - return -1; - - char const * const buf = ptr + 1080; - - if (!strncmp(buf + 2, "CH", 2) && isdigit((int)buf[0]) && isdigit((int)buf[1])) - { - int i = (buf[0] - '0') * 10 + buf[1] - '0'; - if (i > 0 && i <= 32) - return 0; - } - - if (!strncmp(buf + 1, "CHN", 3) && isdigit((int)*buf)) - { - if (*buf >= '0' && *buf <= '9') - return 0; - } - - if (!memcmp(buf, "M.K.", 4)) - return 0; - - return -1; -} - -static int s3m_test_memory(char const *ptr, uint32_t ptrlength) -{ - static char const s3m_magic[] = "SCRM"; - #define s3m_magic_offset 44 - - if (ptrlength < s3m_magic_offset + sizeof(s3m_magic)-1 || - memcmp(ptr + s3m_magic_offset, s3m_magic, sizeof(s3m_magic)-1) || - ptr[29] != 0x10) - return -1; - - return 0; -} - -static int xm_test_memory(char const *ptr, uint32_t ptrlength) -{ - static char const xm_magic[] = "Extended Module: "; - - if (ptrlength < sizeof(xm_magic)-1 || - memcmp(ptr, xm_magic, sizeof(xm_magic)-1)) - return -1; - - return 0; -} - -static int mtm_test_memory(char const *ptr, uint32_t ptrlength) -{ - static char const mtm_magic[] = "MTM\x10"; - - if (ptrlength < sizeof(mtm_magic)-1 || - memcmp(ptr, mtm_magic, sizeof(mtm_magic)-1)) - return -1; - - return 0; -} - -int MV_IdentifyXMP(char const *ptr, uint32_t ptrlength) -{ - static decltype(mod_test_memory) * const module_test_functions[] = - { - it_test_memory, - mod_test_memory, - s3m_test_memory, - xm_test_memory, - mtm_test_memory, - }; - - for (auto const test_module : module_test_functions) - { - if (test_module(ptr, ptrlength) == 0) - return 1; - } - - return 0; -} diff --git a/source/common/initfs.cpp b/source/common/initfs.cpp index 2d0c6192c..4a93a87e0 100644 --- a/source/common/initfs.cpp +++ b/source/common/initfs.cpp @@ -360,6 +360,19 @@ void InitFileSystem(TArray& groups) Files.Push(lastfn); } } + const char* key; + const char* value; + if (GameConfig->SetSection("global.Autoload")) + { + while (GameConfig->NextInSection(key, value)) + { + if (stricmp(key, "Path") == 0) + { + FString nice = NicePath(value); + D_AddFile(Files, nice); + } + } + } TArray todelete; fileSystem.InitMultipleFiles(Files, todelete); diff --git a/source/common/music/music.cpp b/source/common/music/music.cpp index 5360a0304..ca3b816ae 100644 --- a/source/common/music/music.cpp +++ b/source/common/music/music.cpp @@ -75,23 +75,6 @@ MusicVolumeMap MusicVolumes; bool MusicPaused; -void S_CreateStream() -{ -} - -void S_PauseStream(bool pause) -{ -} - -void S_StopStream() -{ - -} - -void S_SetStreamVolume(float vol) -{ - -} //========================================================================== // // starts playing this song diff --git a/source/common/music/musicstream.cpp b/source/common/music/musicstream.cpp new file mode 100644 index 000000000..4fd888920 --- /dev/null +++ b/source/common/music/musicstream.cpp @@ -0,0 +1,137 @@ + +#include "compat.h" + +#include "../../audiolib/src/_multivc.h" +#include "multivoc.h" +#include "../../audiolib/src/pitch.h" +#include "pragmas.h" +#include "zmusic/zmusic.h" +#include "s_music.h" +#include "templates.h" +#include "fx_man.h" +#include "gamecvars.h" + +static short buffer[2][16384]; +static float readbuffer[16384]; +static int whichbuffer; +static bool StreamPaused; +static int StreamHandle; +static VoiceNode* voice; + +static bool FillStream(void* buff, int len) +{ + if (StreamPaused) + { + memset((char*)buff, 0, len); + return true; + } + + bool written = ZMusic_FillStream(mus_playing.handle, buff, len); + + if (!written) + { + memset((char*)buff, 0, len); + return false; + } + return true; +} + + +static playbackstatus MV_GetNextZMusicBlock(VoiceNode *voice) +{ + if (!FillStream(readbuffer, 32768)) + return NoMoreData; + + for (int i = 0; i <16384; i++) + { + buffer[whichbuffer][i] = (short)clamp(readbuffer[i]*32767., -32768., 32767.); + } + + voice->sound = (const char*)buffer[whichbuffer]; + voice->length = 8192; + voice->position = 0; + voice->BlockLength = 0; + whichbuffer ^= 1; + + MV_SetVoiceMixMode(voice); + + return KeepPlaying; +} + +void S_CreateStream() +{ + if (!MV_Installed) + return;// MV_SetErrorCode(MV_NotInstalled); + + // Request a voice from the voice pool + voice = MV_AllocVoice(FX_MUSIC_PRIORITY); + if (voice == nullptr) + { + return;// MV_SetErrorCode(MV_NoVoices); + } + + voice->length = 0; + voice->sound = 0; + + voice->wavetype = FMT_ZMUSIC; + voice->rawdataptr = nullptr; + voice->GetSound = MV_GetNextZMusicBlock; + voice->LoopCount = 0; + voice->BlockLength = 0; + voice->PitchScale = PITCH_GetScale(0); + voice->next = nullptr; + voice->prev = nullptr; + voice->priority = FX_MUSIC_PRIORITY; + voice->callbackval = 0; + + voice->bits = 16; + voice->channels = 2; + voice->SamplingRate = MV_MixRate; + + voice->Paused = FALSE; + + voice->LoopStart = 0; + voice->LoopEnd = 0; + voice->LoopSize = 1; + + // CODEDUP multivoc.c MV_SetVoicePitch + voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate); + voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale; + MV_SetVoiceMixMode(voice); + + mus_volume.Callback(); + MV_PlayVoice(voice); + + return;// voice->handle; +} + +void MV_ReleaseZMusicVoice(VoiceNode * voice) +{ + if (voice->wavetype != FMT_ZMUSIC) + return; + + voice->rawdataptr = 0; + voice->length = 0; + voice->sound = nullptr; + StreamHandle = 0; + ::voice = nullptr; +} + +void S_PauseStream(bool pause) +{ + StreamPaused = true; +} + +void S_StopStream() +{ + if (StreamHandle > 0) + FX_StopSound(StreamHandle); + StreamHandle = 0; + voice = nullptr; +} + +void S_SetStreamVolume(float vol) +{ + if (voice) + MV_SetVoiceVolume(voice, int(vol * 255), int(vol * 255), int(vol * 255), 1); +} diff --git a/source/common/music/s_music.h b/source/common/music/s_music.h index 004e68f8c..bca472f67 100644 --- a/source/common/music/s_music.h +++ b/source/common/music/s_music.h @@ -32,6 +32,11 @@ #include "tarray.h" #include "name.h" +void S_CreateStream(); +void S_PauseStream(bool pause); +void S_StopStream(); +void S_SetStreamVolume(float vol); + // void S_InitMusic ();