#include #include "sample_flac.h" #include "w_wad.h" #include "templates.h" FLACSampleLoader::FLACSampleLoader (sfxinfo_t *sfx) : NumChannels (0), SampleBits (0), SampleRate (0), NumSamples (0), File (Wads.OpenLumpNum (sfx->lumpnum)), Sfx (sfx) { StartPos = File.Tell(); EndPos = StartPos + File.GetLength(); init (); process_until_end_of_metadata (); } FSOUND_SAMPLE *FLACSampleLoader::LoadSample (unsigned int samplemode) { if (NumSamples == 0) { DPrintf ("FLAC has unknown number of samples\n"); return NULL; } FSOUND_SAMPLE *sample; unsigned int mode; unsigned int bits; Sfx->frequency = SampleRate; bits = (SampleBits <= 8) ? FSOUND_8BITS : FSOUND_16BITS; mode = FSOUND_SIGNED | FSOUND_MONO | FSOUND_LOOP_OFF; sample = FSOUND_Sample_Alloc (FSOUND_FREE, NumSamples, samplemode | bits | mode, SampleRate, 255, FSOUND_STEREOPAN, 255); if (sample == NULL) { bits ^= FSOUND_8BITS | FSOUND_16BITS; sample = FSOUND_Sample_Alloc (FSOUND_FREE, NumSamples, samplemode | bits | mode, SampleRate, 255, FSOUND_STEREOPAN, 255); if (sample == NULL) { return sample; } } void *ptr1, *ptr2; unsigned int len1, len2; if (!FSOUND_Sample_Lock (sample, 0, bits & FSOUND_8BITS ? NumSamples : NumSamples * 2, &ptr1, &ptr2, &len1, &len2)) { FSOUND_Sample_Free (sample); DPrintf ("Failed locking FLAC sample\n"); return NULL; } SBuff = ptr1; SBuff2 = ptr2; SLen = len1; SLen2 = len2; Dest8 = (bits & FSOUND_8BITS) ? true : false; if (!process_until_end_of_stream ()) { FSOUND_Sample_Unlock (sample, ptr1, ptr2, len1, len2); FSOUND_Sample_Free (sample); DPrintf ("Failed loading FLAC sample\n"); return NULL; } FSOUND_Sample_Unlock (sample, ptr1, ptr2, len1, len2); return sample; } BYTE *FLACSampleLoader::ReadSample (SDWORD *numbytes) { if (NumSamples == 0) { DPrintf ("FLAC has unknown number of samples\n"); return NULL; } BYTE *sfxdata; Sfx->frequency = SampleRate; Sfx->b16bit = (SampleBits > 8); sfxdata = new BYTE[NumSamples << Sfx->b16bit]; SBuff = sfxdata; SBuff2 = NULL; SLen = NumSamples; SLen2 = 0; Dest8 = !Sfx->b16bit; *numbytes = NumSamples << Sfx->b16bit; if (!process_until_end_of_stream ()) { DPrintf ("Failed loading FLAC sample\n"); delete[] sfxdata; return NULL; } return sfxdata; } FLACSampleLoader::~FLACSampleLoader () { } void FLACSampleLoader::CopyToSample (size_t ofs, FLAC__int32 **buffer, size_t ilen) { size_t i; size_t len = MIN (ilen, SLen); FLAC__int32 *buffer0 = buffer[0] + ofs; if (SampleBits == 16) { if (!Dest8) { SWORD *buff = (SWORD *)SBuff; if (NumChannels == 1) { // Mono16 -> Mono16 for (i = 0; i < len; ++i) { buff[i] = SWORD(buffer0[i]); } } else { // Stereo16 -> Mono16 FLAC__int32 *buffer1 = buffer[1] + ofs; for (i = 0; i < len; ++i) { buff[i] = (buffer0[i] + buffer1[i]) / 2; } } SBuff = buff + i; } else { SBYTE *buff = (SBYTE *)SBuff; if (NumChannels == 1) { // Mono16 -> Mono8 for (i = 0; i < len; ++i) { buff[i] = buffer0[i] / 256; } } else { // Stereo16 -> Mono8 FLAC__int32 *buffer1 = buffer[1] + ofs; for (i = 0; i < len; ++i) { buff[i] = (buffer0[i] + buffer1[i]) / 512; } } SBuff = buff + i; } } else if (SampleBits == 8) { if (Dest8) { SBYTE *buff = (SBYTE *)SBuff; if (NumChannels == 1) { // Mono8 -> Mono8 for (i = 0; i < len; ++i) { buff[i] = SBYTE(buffer0[i]); } } else { // Stereo8 -> Mono8 FLAC__int32 *buffer1 = buffer[1] + ofs; for (i = 0; i < len; ++i) { buff[i*2] = SBYTE(buffer0[i]); buff[i*2+1] = SBYTE(buffer1[i]); } } SBuff = buff + i; } else { SWORD *buff = (SWORD *)SBuff; if (NumChannels == 1) { // Mono8 -> Mono16 for (i = 0; i < len; ++i) { buff[i] = buffer0[i] * 257; } } else { // Stereo8 -> Mono16 FLAC__int32 *buffer1 = buffer[1] + ofs; for (i = 0; i < len; ++i) { buff[i*2] = ((buffer0[i] + buffer1[i]) / 2) * 257; } } SBuff = buff + i; } } // If the lock was split into two buffers, do the other one next. // (Will this ever happen? Don't think so, but...) if (ilen > len) { SBuff = SBuff2; SLen = SLen2; SBuff2 = NULL; SLen2 = 0; if (SLen > 0) { CopyToSample (len, buffer, ilen - len); } } } ::FLAC__StreamDecoderReadStatus FLACSampleLoader::read_callback(FLAC__byte buffer[], unsigned *bytes) { if (*bytes > 0) { long here = File.Tell(); if (here == EndPos) { return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; } else { if (*bytes > (size_t)(EndPos - here)) { *bytes = EndPos - here; } File.Read (buffer, *bytes); return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } } else { return FLAC__STREAM_DECODER_READ_STATUS_ABORT; } } ::FLAC__StreamDecoderWriteStatus FLACSampleLoader::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) { CopyToSample (0, (FLAC__int32 **)buffer, frame->header.blocksize); return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } void FLACSampleLoader::metadata_callback(const ::FLAC__StreamMetadata *metadata) { if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { switch (metadata->data.stream_info.bits_per_sample) { case 8: case 16: break; default: DPrintf ("Only FLACs with 8 or 16 bits per sample are supported\n"); return; } if (metadata->data.stream_info.total_samples > 0xFFFFFFFF) { DPrintf ("FLAC is too long\n"); } SampleRate = metadata->data.stream_info.sample_rate; NumChannels = (unsigned int)MIN (2u, metadata->data.stream_info.channels); SampleBits = metadata->data.stream_info.bits_per_sample; NumSamples = (unsigned int)metadata->data.stream_info.total_samples; } } void FLACSampleLoader::error_callback(::FLAC__StreamDecoderErrorStatus status) { status = status; }