Commit 09dc0cc9 authored by Richard Gobeille's avatar Richard Gobeille
Browse files

audiolib: cleanups and consolidations

Zeroing of fields when starting playback moved to common functions, revised allocation of memory for FLAC, Vorbis, XA, and XMP, addition of "snd_lazyalloc" cvar to control reusal of memory blocks allocated for Vorbis, XA, and XMP playback, other misc code cleanup.
parent 6e54cbb1
......@@ -61,7 +61,6 @@ enum MV_Errors
MV_NotInstalled,
MV_DriverError,
MV_NoVoices,
MV_NoMem,
MV_VoiceNotFound,
MV_InvalidFile,
};
......
......@@ -57,70 +57,35 @@ extern struct VoiceNode VoiceList;
extern struct VoiceNode VoicePool;
extern fix16_t MV_GlobalVolume;
extern fix16_t MV_VolumeSmooth;
extern fix16_t MV_VolumeSmoothFactor;
static FORCE_INLINE fix16_t SMOOTH_VOLUME(fix16_t const volume, fix16_t const dest)
{
return volume + fix16_fast_trunc_mul(dest - volume, MV_VolumeSmooth);
}
static FORCE_INLINE fix16_t SMOOTH_VOLUME(fix16_t const volume, fix16_t const dest) { return volume + fix16_fast_trunc_mul(dest - volume, MV_VolumeSmoothFactor); }
template <typename T>
static inline conditional_t< is_signed<T>::value, make_unsigned_t<T>, make_signed_t<T> > FLIP_SIGN(T src)
template <typename T> static inline conditional_t<is_signed<T>::value, make_unsigned_t<T>, make_signed_t<T>> FLIP_SIGN(T src)
{
static constexpr make_unsigned_t<T> msb = ((make_unsigned_t<T>)1) << (sizeof(T) * CHAR_BIT - 1u);
return src ^ msb;
}
template <typename T>
static inline enable_if_t<is_signed<T>::value, T> SCALE_SAMPLE(T src, fix16_t volume)
template <typename T> static inline enable_if_t<is_signed<T>::value, T> SCALE_SAMPLE(T src, fix16_t volume)
{
return (T)fix16_fast_trunc_mul_int_by_fix16(src, volume);
}
template <typename T>
static inline T CONVERT_SAMPLE_FROM_SIGNED(int src);
template<>
inline int16_t CONVERT_SAMPLE_FROM_SIGNED<int16_t>(int src)
{
return src;
}
template <typename T>
static inline int CONVERT_SAMPLE_TO_SIGNED(T src);
template<>
inline int CONVERT_SAMPLE_TO_SIGNED<int16_t>(int16_t src)
{
return src;
}
template <typename S, typename D>
static inline int CONVERT_LE_SAMPLE_TO_SIGNED(S src);
template<>
inline int CONVERT_LE_SAMPLE_TO_SIGNED<uint8_t, int16_t>(uint8_t src)
{
return FLIP_SIGN(src) << 8;
}
template <typename T> static inline T CONVERT_SAMPLE_FROM_SIGNED(int src);
template <> inline int16_t CONVERT_SAMPLE_FROM_SIGNED<int16_t>(int src) { return src; }
template<>
inline int CONVERT_LE_SAMPLE_TO_SIGNED<int16_t, int16_t>(int16_t src)
{
return B_LITTLE16(src);
}
template <typename T> static inline int CONVERT_SAMPLE_TO_SIGNED(T src);
template <> inline int CONVERT_SAMPLE_TO_SIGNED<int16_t>(int16_t src) { return src; }
template <typename T>
static int CLAMP_SAMPLE(int src);
template <typename S, typename D> static inline int CONVERT_LE_SAMPLE_TO_SIGNED(S src);
template <> inline int CONVERT_LE_SAMPLE_TO_SIGNED<uint8_t, int16_t>(uint8_t src) { return FLIP_SIGN(src) << 8; }
template <> inline int CONVERT_LE_SAMPLE_TO_SIGNED<int16_t, int16_t>(int16_t src) { return B_LITTLE16(src); }
template<>
inline int CLAMP_SAMPLE<int16_t>(int src)
{
return clamp(src, INT16_MIN, INT16_MAX);
}
template <typename T> static int CLAMP_SAMPLE(int src);
template <> inline int CLAMP_SAMPLE<int16_t>(int src) { return clamp(src, INT16_MIN, INT16_MAX); }
template <typename T>
static T MIX_SAMPLES(int signed_sample, T untouched_sample)
template <typename T> static T MIX_SAMPLES(int signed_sample, T untouched_sample)
{
return CONVERT_SAMPLE_FROM_SIGNED<T>(CLAMP_SAMPLE<T>(signed_sample + CONVERT_SAMPLE_TO_SIGNED<T>(untouched_sample)));
}
......@@ -164,9 +129,6 @@ typedef struct VoiceNode
const char *sound;
fix16_t LeftVolume, LeftVolumeDest;
fix16_t RightVolume, RightVolumeDest;
union
{
void *rawdataptr;
......@@ -174,21 +136,33 @@ typedef struct VoiceNode
};
const char *NextBlock;
const char *LoopStart;
const char *LoopEnd;
struct
{
const char *Start;
const char *End;
int Count;
uint32_t Size;
} Loop;
intptr_t callbackval;
struct
{
fix16_t Left;
fix16_t Right;
} PannedVolume, GoalVolume;
wavefmt_t wavetype;
char bits;
char channels;
char ptrlock;
int bits;
int channels;
fix16_t volume;
int LoopCount;
uint32_t LoopSize;
uint32_t BlockLength;
int ptrlength; // ptrlength-1 is the max permissible index for rawdataptr
uint32_t rawdatasiz; // rawdatasiz-1 is the max permissible index for rawdataptr
uint32_t PitchScale;
uint32_t FixedPointBufferSize;
......@@ -202,8 +176,6 @@ typedef struct VoiceNode
int handle;
int priority;
intptr_t callbackval;
void *userdata;
} VoiceNode;
typedef struct
......@@ -243,6 +215,7 @@ extern int MV_Installed;
extern int MV_MixRate;
extern char *MV_MusicBuffer;
extern int MV_BufferSize;
extern int MV_LazyAlloc;
extern int MV_MaxVoices;
extern int MV_Channels;
......@@ -260,7 +233,7 @@ static FORCE_INLINE int MV_SetErrorCode(int status)
void MV_PlayVoice(VoiceNode *voice);
VoiceNode *MV_AllocVoice(int priority);
VoiceNode *MV_AllocVoice(int priority, uint32_t allocsize = 0);
void MV_SetVoiceMixMode(VoiceNode *voice);
void MV_SetVoiceVolume(VoiceNode *voice, int vol, int left, int right, fix16_t volume);
......
......@@ -224,19 +224,18 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
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)
if ((FLAC__uint64)(uintptr_t)voice->Loop.End > 0 &&
fd->sample_pos + samples >= (FLAC__uint64)(uintptr_t)voice->Loop.End)
{
samples = (FLAC__uint64)(uintptr_t)voice->LoopEnd - fd->sample_pos;
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart))
samples = (FLAC__uint64)(uintptr_t)voice->Loop.End - fd->sample_pos;
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->Loop.Start))
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);
(FLAC__uint64)(uintptr_t)voice->Loop.Start, (FLAC__uint64)(uintptr_t)voice->Loop.End);
}
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;
......@@ -246,7 +245,7 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
if (size > fd->blocksize)
{
block = (char *)Xmalloc(size);
block = (char *)Xaligned_alloc(16, size);
if (block == nullptr)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
......@@ -279,7 +278,7 @@ FLAC__StreamDecoderWriteStatus write_flac_stream(const FLAC__StreamDecoder *deco
char * oldblock = fd->block;
fd->block = block;
fd->blocksize = size;
Xfree(oldblock);
ALIGNED_FREE_AND_NULL(oldblock);
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
......@@ -324,10 +323,10 @@ static playbackstatus MV_GetNextFLACBlock(VoiceNode *voice)
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))
if ((FLAC__uint64)(uintptr_t)voice->Loop.End > 0 && fd->sample_pos >= (FLAC__uint64)(uintptr_t)voice->Loop.End)
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->Loop.Start))
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);
(FLAC__uint64)(uintptr_t)voice->Loop.Start, (FLAC__uint64)(uintptr_t)voice->Loop.End);
/*decode_status =*/FLAC__stream_decoder_process_single(fd->stream);
decode_state = FLAC__stream_decoder_get_state(fd->stream);
......@@ -348,11 +347,11 @@ static playbackstatus MV_GetNextFLACBlock(VoiceNode *voice)
if (decode_state == FLAC__STREAM_DECODER_END_OF_STREAM)
{
if (voice->LoopSize > 0)
if (voice->Loop.Size > 0)
{
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->LoopStart))
if (!FLAC__stream_decoder_seek_absolute(fd->stream, (FLAC__uint64)(uintptr_t)voice->Loop.Start))
MV_Printf("MV_GetNextFLACBlock FLAC__stream_decoder_seek_absolute: LOOP_START %ul\n",
(FLAC__uint64)(uintptr_t)voice->LoopStart);
(FLAC__uint64)(uintptr_t)voice->Loop.Start);
}
else
return NoMoreData;
......@@ -421,27 +420,25 @@ priority.
int MV_PlayFLAC(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, int left, int right, int priority, fix16_t 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;
// Request a voice from the voice pool
auto voice = MV_AllocVoice(priority, sizeof(flac_data));
if (voice == nullptr)
return MV_SetErrorCode(MV_NoVoices);
fd->block = nullptr;
auto fd = (flac_data *)voice->rawdataptr;
fd->stream = FLAC__stream_decoder_new();
fd->owner = voice;
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);
......@@ -451,40 +448,19 @@ int MV_PlayFLAC(char *ptr, uint32_t length, int loopstart, int loopend, int pitc
/*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));
ALIGNED_FREE_AND_NULL(fd);
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);
voice->Loop = { nullptr, nullptr, 0, loopstart >= 0 };
// parse metadata
// loop parsing designed with multiple repetitions in mind
......@@ -492,7 +468,7 @@ int MV_PlayFLAC(char *ptr, uint32_t length, int loopstart, int loopend, int pitc
// &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();
auto metadata_chain = FLAC__metadata_chain_new();
if (metadata_chain != nullptr)
{
if (FLAC__metadata_chain_read_with_callbacks(metadata_chain, fd, flac_callbacks))
......@@ -521,7 +497,7 @@ int MV_PlayFLAC(char *ptr, uint32_t length, int loopstart, int loopend, int pitc
// FLAC__metadata_chain_delete(metadata_chain);
FLAC__stream_decoder_finish(fd->stream);
FLAC__stream_decoder_delete(fd->stream);
Xfree(fd);
ALIGNED_FREE_AND_NULL(fd);
return MV_SetErrorCode(MV_InvalidFile);
}
......@@ -577,29 +553,29 @@ int MV_PlayFLAC(char *ptr, uint32_t length, int loopstart, int loopend, int pitc
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;
voice->Loop.Start = (const char *)(intptr_t)flac_loopstart;
voice->Loop.Size = 1;
}
}
Xfree(vc_loopstart);
}
if (vc_loopend != nullptr)
{
if (voice->LoopSize > 0)
if (voice->Loop.Size > 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;
voice->Loop.End = (const char *)(intptr_t)flac_loopend;
}
Xfree(vc_loopend);
}
if (vc_looplength != nullptr)
{
if (voice->LoopSize > 0 && voice->LoopEnd == 0)
if (voice->Loop.Size > 0 && voice->Loop.End == 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);
voice->Loop.End = (const char *)((intptr_t)flac_looplength + (intptr_t)voice->Loop.Start);
}
Xfree(vc_looplength);
}
......@@ -632,11 +608,11 @@ int MV_PlayFLAC(char *ptr, uint32_t length, int loopstart, int loopend, int pitc
void MV_ReleaseFLACVoice(VoiceNode *voice)
{
if (voice->wavetype != FMT_FLAC || voice->rawdataptr == nullptr)
return;
Bassert(voice->wavetype == FMT_FLAC && voice->rawdataptr != nullptr && voice->rawdatasiz == sizeof(flac_data));
flac_data *fd = (flac_data *)voice->rawdataptr;
voice->rawdataptr = nullptr;
voice->rawdatasiz = 0;
if (fd->stream != nullptr)
{
......@@ -650,8 +626,8 @@ void MV_ReleaseFLACVoice(VoiceNode *voice)
auto block = fd->block;
fd->block = nullptr;
Xfree(block);
Xfree(fd);
ALIGNED_FREE_AND_NULL(block);
ALIGNED_FREE_AND_NULL(fd);
}
#else
#include "_multivc.h"
......
......@@ -34,11 +34,11 @@ static playbackstatus MV_GetNextWAVBlock(VoiceNode *voice)
{
if (voice->BlockLength == 0)
{
if (voice->LoopStart == nullptr)
if (voice->Loop.Start == nullptr)
return NoMoreData;
voice->BlockLength = voice->LoopSize;
voice->NextBlock = voice->LoopStart;
voice->BlockLength = voice->Loop.Size;
voice->NextBlock = voice->Loop.Start;
voice->length = 0;
voice->position = 0;
}
......@@ -95,7 +95,7 @@ static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
// terminator is not mandatory according to
// http://wiki.multimedia.cx/index.php?title=Creative_Voice
if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
if (ptr - (uint8_t *)voice->rawdataptr >= voice->rawdatasiz)
blocktype = 0; // fake a terminator
else
blocktype = *ptr;
......@@ -114,14 +114,14 @@ static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice)
case 0 :
end_of_data:
// End of data
if ((voice->LoopStart == nullptr) ||
((intptr_t) voice->LoopStart >= ((intptr_t) ptr - 4)))
if ((voice->Loop.Start == nullptr) ||
((intptr_t) voice->Loop.Start >= ((intptr_t) ptr - 4)))
{
done = 2;
}
else
{
voice->NextBlock = voice->LoopStart;
voice->NextBlock = voice->Loop.Start;
voice->BlockLength = 0;
voice->position = 0;
return MV_GetNextVOCBlock(voice);
......@@ -149,7 +149,7 @@ end_of_data:
else
done = TRUE;
if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
if (ptr - (uint8_t *)voice->rawdataptr >= voice->rawdatasiz)
goto end_of_data;
voicemode = 0;
......@@ -173,10 +173,10 @@ end_of_data:
case 6 :
// Repeat begin
if (voice->LoopEnd == nullptr)
if (voice->Loop.End == nullptr)
{
voice->LoopCount = B_LITTLE16(*(uint16_t const *)ptr);
voice->LoopStart = (char *)((intptr_t) ptr + blocklength);
voice->Loop.Count = B_LITTLE16(*(uint16_t const *)ptr);
voice->Loop.Start = (char *)((intptr_t) ptr + blocklength);
}
ptr += blocklength;
break;
......@@ -185,17 +185,17 @@ end_of_data:
// Repeat end
ptr += blocklength;
if (lastblocktype == 6)
voice->LoopCount = 0;
voice->Loop.Count = 0;
else
{
if ((voice->LoopCount > 0) && (voice->LoopStart != nullptr))
if ((voice->Loop.Count > 0) && (voice->Loop.Start != nullptr))
{
ptr = (uint8_t const *) voice->LoopStart;
ptr = (uint8_t const *) voice->Loop.Start;
if (voice->LoopCount < 0xffff)
if (voice->Loop.Count < 0xffff)
{
if (--voice->LoopCount == 0)
voice->LoopStart = nullptr;
if (--voice->Loop.Count == 0)
voice->Loop.Start = nullptr;
}
}
}
......@@ -242,7 +242,7 @@ end_of_data:
// CAUTION:
// SNAKRM.VOC is corrupt! blocklength gets us beyond the
// end of the file.
if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength)
if (ptr - (uint8_t *)voice->rawdataptr >= voice->rawdatasiz)
goto end_of_data;
break;
......@@ -270,16 +270,16 @@ end_of_data:
voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) -
voice->RateScale;
if (voice->LoopEnd != nullptr)
if (voice->Loop.End != nullptr)
{
if (blocklength > (uintptr_t)voice->LoopEnd)
blocklength = (uintptr_t)voice->LoopEnd;
if (blocklength > (uintptr_t)voice->Loop.End)
blocklength = (uintptr_t)voice->Loop.End;
else
voice->LoopEnd = (char *)blocklength;
voice->Loop.End = (char *)blocklength;
voice->LoopStart = voice->sound + (uintptr_t)voice->LoopStart;
voice->LoopEnd = voice->sound + (uintptr_t)voice->LoopEnd;
voice->LoopSize = voice->LoopEnd - voice->LoopStart;
voice->Loop.Start = voice->sound + (uintptr_t)voice->Loop.Start;
voice->Loop.End = voice->sound + (uintptr_t)voice->Loop.End;
voice->Loop.Size = voice->Loop.End - voice->Loop.Start;
}
if (voice->bits == 16)
......@@ -305,11 +305,11 @@ static playbackstatus MV_GetNextRAWBlock(VoiceNode *voice)
{
if (voice->BlockLength == 0)
{
if (voice->LoopStart == NULL)
if (voice->Loop.Start == NULL)
return NoMoreData;
voice->BlockLength = voice->LoopSize;
voice->NextBlock = voice->LoopStart;
voice->BlockLength = voice->Loop.Size;
voice->NextBlock = voice->Loop.Start;
voice->length = 0;
voice->position = 0;
}
......@@ -379,7 +379,7 @@ int MV_PlayWAV(char *ptr, uint32_t length, int loopstart, int loopend, int pitch
// Request a voice from the voice pool
VoiceNode *voice = MV_AllocVoice(priority);
auto voice = MV_AllocVoice(priority);
if (voice == nullptr)
return MV_SetErrorCode(MV_NoVoices);
......@@ -403,21 +403,17 @@ int MV_PlayWAV(char *ptr, uint32_t length, int loopstart, int loopend, int pitch
blocklen /= 2;
}
voice->rawdataptr = (uint8_t *)ptr;
voice->ptrlength = length;
voice->Paused = FALSE;
voice->LoopCount = 0;
voice->position = 0;
voice->length = 0;
voice->BlockLength = blocklen;
voice->NextBlock = (char *)((intptr_t) ptr + sizeof(riff_header) + riff.format_size + sizeof(data_header));
voice->next = nullptr;
voice->prev = nullptr;
voice->priority = priority;
voice->callbackval = callbackval;
voice->LoopStart = loopstart >= 0 ? voice->NextBlock : nullptr;
voice->LoopEnd = nullptr;
voice->LoopSize = loopend > 0 ? loopend - loopstart + 1 : blocklen;
voice->rawdataptr = (uint8_t *)ptr;
voice->rawdatasiz = length;
voice->position = 0;
voice->BlockLength = blocklen;
voice->NextBlock = (char *)((intptr_t)ptr + sizeof(riff_header) + riff.format_size + sizeof(data_header));
voice->priority = priority;
voice->callbackval = callbackval;
voice->Loop.Start = loopstart >= 0 ? voice->NextBlock : nullptr;
voice->Loop.End = nullptr;
voice->Loop.Count = 0;
voice->Loop.Size = loopend > 0 ? loopend - loopstart + 1 : blocklen;
MV_SetVoicePitch(voice, format.nSamplesPerSec, pitchoffset);
MV_SetVoiceVolume(voice, vol, left, right, volume);
......@@ -458,30 +454,22 @@ int MV_PlayVOC(char *ptr, uint32_t length, int loopstart, int loopend, int pitch
return MV_SetErrorCode(MV_InvalidFile);
// Request a voice from the voice pool
VoiceNode *voice = MV_AllocVoice(priority);
auto voice = MV_AllocVoice(priority);
if (voice == nullptr)
return MV_SetErrorCode(MV_NoVoices);
voice->rawdataptr = (uint8_t *)ptr;
voice->ptrlength = length;
voice->Paused = FALSE;
voice->rawdataptr = (uint8_t *)ptr;
voice->rawdatasiz = length;
voice->wavetype = FMT_VOC;
voice->bits = 8;
voice->channels = 1;
voice->GetSound = MV_GetNextVOCBlock;
voice->NextBlock = ptr + B_LITTLE16(*(uint16_t *)(ptr + 0x14));
voice->LoopCount = 0;
voice->BlockLength = 0;
voice->PitchScale = PITCH_GetScale(pitchoffset);
voice->length = 0;
voice->next = nullptr;
voice->prev = nullptr;
voice->priority = priority;
voice->callbackval = callbackval;