Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "_sfx.hpp"
- #include <file.hpp>
- static inline bool _format_invalid(SDL_AudioFormat format){
- if(format == AUDIO_U8 ) return false;
- if(format == AUDIO_S16) return false;
- if(format == AUDIO_F32) return false;
- return true; //any other format is invalid
- }
- union _every_sample_type {
- void* data;
- Uint8* u8;
- Sint16* i16;
- float* f32;
- sfx_u8s* u8s;
- sfx_i16s* i16s;
- sfx_f32s* f32s;
- };
- #define _FORMAT_SWITCH(_channels, _format) ( ((_channels)<<16) | (_format) )
- enum _format_switch_enum {
- fmt_u8 = _FORMAT_SWITCH(1,AUDIO_U8 ),
- fmt_i16 = _FORMAT_SWITCH(1,AUDIO_S16),
- fmt_f32 = _FORMAT_SWITCH(1,AUDIO_F32),
- fmt_u8s = _FORMAT_SWITCH(2,AUDIO_U8 ),
- fmt_i16s = _FORMAT_SWITCH(2,AUDIO_S16),
- fmt_f32s = _FORMAT_SWITCH(2,AUDIO_F32),
- };
- sfx_pcm::sfx_pcm(const std::string& filePath,
- const sfx_class* sfx_ptr)
- {
- sfx = (sfx_class*)sfx_ptr;
- int deviceSampleRate = DEFAULT_SAMPLERATE;
- if(sfx != nullptr) deviceSampleRate = sfx->getSampleRate();
- if(deviceSampleRate < 1000) throw "sfx->_sampleRate < 1000";
- if(deviceSampleRate > 384000) throw "sfx->_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();
- 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()-sizeof(sfx_pcm))) throw "dataSize is invalid";
- if(hdr->loopStart >= hdr->numSamples) throw "loopStart >= numSamples";
- if(hdr->loopEnd > hdr->numSamples) throw "loopEnd >= numSamples";
- if(hdr->numSamples != (hdr->dataSize/((hdr->format&255)/8))/hdr->channels) throw "numSamples is invalid";
- if(hdr->sampleRate < 1000) throw "sampleRate < 1000";
- if(hdr->bitRate != hdr->sampleRate*hdr->channels*(hdr->format&255)*hdr->channels) throw "bitRate is invalid";
- if(hdr->channels!=1 && hdr->channels!=2) throw "channels are neither mono nor stereo";
- 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
- 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
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement