Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "_sfx.hpp"
- #include <file.hpp>
- sfx_pcm::sfx_pcm(const std::string& filePath,
- const sfx_class* sfx_ptr)
- {
- int deviceSampleRate = DEFAULT_SAMPLERATE;
- if(sfx_ptr != nullptr) deviceSampleRate = sfx_ptr->getSampleRate();
- if(deviceSampleRate < 1000) throw "sfx_ptr->_sampleRate < 1000";
- if(deviceSampleRate > 384000) throw "sfx_ptr->_sampleRate > 384000";
- //load pcm data
- std::vector<char> fileDataIn = file_readBin(filePath);
- if(fileDataIn.size() < sizeof(sfx_pcm)) throw "fileSize < sizeof(sfx_pcm)";
- //header validation stuff
- sfx_pcm* hdr = (sfx_pcm*)fileDataIn.data();
- //hdr->print(); //for debug
- if(hdr->magic != SFX_PCM_MAGIC) throw "magic != SFX_PCM_MAGIC";
- if(_format_invalid(hdr->format)) throw "format is invalid";
- if(hdr->headerSize < sizeof(sfx_pcm)) throw "headerSize < sizeof(sfx_pcm)";
- if(hdr->dataSize != (fileDataIn.size()-hdr->headerSize)) throw "dataSize is invalid";
- //(numSamples is checked before loopStart/loopEnd, as their checks rely upon numSamples)
- if(hdr->numSamples != (hdr->dataSize/((hdr->format&255)/8))/hdr->channels) throw "numSamples is invalid";
- if(hdr->loopStart >= hdr->numSamples) throw "loopStart >= numSamples";
- if(hdr->loopEnd > hdr->numSamples) throw "loopEnd > numSamples";
- //(channels are checked before numSamples to prevent divide-by-zero exceptions)
- if(hdr->channels!=1 && hdr->channels!=2) throw "audio is neither mono nor stereo";
- if(hdr->sampleRate < 1000) throw "sampleRate < 1000";
- if(hdr->bitRate != hdr->sampleRate*hdr->channels*(hdr->format&255)) throw "bitRate is invalid";
- void* smpData = fileDataIn.data() + hdr->headerSize;
- //convert data type to float stereo
- Uint64 numSamplesIn = hdr->numSamples;
- std::vector<sfx_f32s> samplesF32S(numSamplesIn);
- _every_sample_type smp = { .data = smpData };
- switch(_FORMAT_SWITCH(hdr->channels,hdr->format)){
- case fmt_u8 : for(Uint64 i=0; i<numSamplesIn; ++i) samplesF32S[i] = smp.u8 [i]; break;
- case fmt_i16 : for(Uint64 i=0; i<numSamplesIn; ++i) samplesF32S[i] = smp.i16 [i]; break;
- case fmt_f32 : for(Uint64 i=0; i<numSamplesIn; ++i) samplesF32S[i] = smp.f32 [i]; break;
- case fmt_u8s : for(Uint64 i=0; i<numSamplesIn; ++i) samplesF32S[i] = smp.u8s [i]; break;
- case fmt_i16s: for(Uint64 i=0; i<numSamplesIn; ++i) samplesF32S[i] = smp.i16s[i]; break;
- case fmt_f32s: for(Uint64 i=0; i<numSamplesIn; ++i) samplesF32S[i] = smp.f32s[i]; break;
- default: throw "channels/format is invalid (this exception should be impossible)";
- }
- //set relevant header values
- *this = *hdr;
- magic = 0;
- format = AUDIO_F32;
- channels = 2;
- sfx = (sfx_class*)sfx_ptr;
- //--------------------------------------------------------
- double inRatio = (double)hdr->sampleRate/deviceSampleRate;
- numSamples = ( ((double)hdr->numSamples)/inRatio ) + 0.5;
- loopStart = ( ((double)hdr->loopStart )/inRatio ) + 0.5;
- loopEnd = ( ((double)hdr->loopEnd )/inRatio ) + 0.5;
- dataSize = numSamples * sizeof(sfx_f32s);
- sampleRate = deviceSampleRate;
- bitRate = deviceSampleRate * sizeof(sfx_f32s) * 8;
- loopCount = hdr->loopCount;
- if(numSamples == 0) throw "output's numSamples was equal to 0";
- samples = new std::vector<sfx_f32s>(numSamples);
- std::vector<sfx_f32s>& samplesRef = *samples; //reference to output samples
- //do linear sample rate conversion, with a target of deviceSampleRate
- --numSamplesIn; // = highest element index of input samples
- Uint64 numSamplesOut = numSamples - 1; // = highest element index of output samples
- double inPosition = 0, inSpeed = (double)numSamplesIn/numSamplesOut;
- if(inSpeed <= 0) throw "sample rate conversion delta <= 0"; //just in case
- for(Uint64 i=0; i<numSamplesOut; ++i){
- samplesRef[i] = sfx_linearSample(samplesF32S, inPosition);
- inPosition += inSpeed;
- }
- //handle last sample separately to (hopefully) account for any previous rounding errors
- samplesRef[numSamplesOut] = samplesF32S.at(numSamplesIn);
- magic = SFX_PCM_MAGIC; //signature is set properly to indicate success
- }
- void sfx_pcm::print(const size_t samplesToPrint){
- SDL_Log("magic = \"%.4s\" (0x%08X)", (char*)&magic, magic);
- switch(format){
- case AUDIO_U8 : SDL_Log("format = AUDIO_U8 (0x%04X)", format); break;
- case AUDIO_S16: SDL_Log("format = AUDIO_S16 (0x%04X)", format); break;
- case AUDIO_F32: SDL_Log("format = AUDIO_F32 (0x%04X)", format); break;
- default: SDL_Log("format = UNKNOWN (0x%04X)", format); }
- SDL_Log("headerSize = %u", headerSize);
- SDL_Log("dataSize = %u", (unsigned)dataSize); //overflows if dataSize > 4GB
- SDL_Log("loopStart = %u", (unsigned)loopStart);
- SDL_Log("loopEnd = %u", (unsigned)loopEnd);
- SDL_Log("numSamples = %u", (unsigned)numSamples);
- SDL_Log("sampleRate = %u", sampleRate);
- SDL_Log("bitrate = %u", bitRate);
- SDL_Log("loopCount = %u", loopCount);
- SDL_Log("channels = %u", channels);
- SDL_Log("bitRemainder = %u", bitRemainder);
- SDL_Log("userflags = 0x%02X", userflags);
- SDL_Log("mode = %u", mode);
- if(samplesToPrint > 0){
- if(format!=AUDIO_F32 || channels!=2) throw "data type is not f32s";
- Uint64 sampleRange = std::min(samplesToPrint, numSamples);
- std::vector<sfx_f32s>& samplesRef = *samples;
- for(Uint32 i=0; i<sampleRange; ++i)
- SDL_Log("%4u: %7.4f, %7.4f", i, samplesRef.at(i).l,samplesRef.at(i).r);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement