Audio-TinySoundFont
view release on metacpan or search on metacpan
TinySoundFont/tsf.h view on Meta::CPAN
if (zoneRegion.end && zoneRegion.end < fontSampleCount) zoneRegion.end++;
else zoneRegion.end = fontSampleCount;
preset->regions[region_index] = zoneRegion;
region_index++;
hadSampleID = 1;
}
else tsf_region_operator(&zoneRegion, pigen->genOper, &pigen->genAmount, TSF_NULL);
}
// Handle instrument's global zone.
if (pibag == hydra->ibags + pinst->instBagNdx && !hadSampleID)
instRegion = zoneRegion;
// Modulators (TODO)
//if (ibag->instModNdx < ibag[1].instModNdx) addUnsupportedOpcode("any modulator");
}
hadGenInstrument = 1;
}
else tsf_region_operator(&presetRegion, ppgen->genOper, &ppgen->genAmount, TSF_NULL);
}
// Modulators (TODO)
//if (pbag->modNdx < pbag[1].modNdx) addUnsupportedOpcode("any modulator");
// Handle preset's global zone.
if (ppbag == hydra->pbags + pphdr->presetBagNdx && !hadGenInstrument)
globalRegion = presetRegion;
}
}
return 1;
}
#ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
static int tsf_decode_ogg(const tsf_u8 *pSmpl, const tsf_u8 *pSmplEnd, float** pRes, tsf_u32* pResNum, tsf_u32* pResMax, tsf_u32 resInitial)
{
float *res = *pRes, *oldres; tsf_u32 resNum = *pResNum; tsf_u32 resMax = *pResMax; stb_vorbis *v;
// Use whatever stb_vorbis API that is available (either pull or push)
#if !defined(STB_VORBIS_NO_PULLDATA_API) && !defined(STB_VORBIS_NO_FROMMEMORY)
v = stb_vorbis_open_memory(pSmpl, (int)(pSmplEnd - pSmpl), TSF_NULL, TSF_NULL);
#else
{ int use, err; v = stb_vorbis_open_pushdata(pSmpl, (int)(pSmplEnd - pSmpl), &use, &err, TSF_NULL); pSmpl += use; }
#endif
if (v == TSF_NULL) return 0;
for (;;)
{
float** outputs; int n_samples;
// Decode one frame of vorbis samples with whatever stb_vorbis API that is available
#if !defined(STB_VORBIS_NO_PULLDATA_API) && !defined(STB_VORBIS_NO_FROMMEMORY)
n_samples = stb_vorbis_get_frame_float(v, TSF_NULL, &outputs);
if (!n_samples) break;
#else
if (pSmpl >= pSmplEnd) break;
{ int use = stb_vorbis_decode_frame_pushdata(v, pSmpl, (int)(pSmplEnd - pSmpl), TSF_NULL, &outputs, &n_samples); pSmpl += use; }
if (!n_samples) continue;
#endif
// Expand our output buffer if necessary then copy over the decoded frame samples
resNum += n_samples;
if (resNum > resMax)
{
do { resMax += (resMax ? (resMax < 1048576 ? resMax : 1048576) : resInitial); } while (resNum > resMax);
res = (float*)TSF_REALLOC((oldres = res), resMax * sizeof(float));
if (!res) { TSF_FREE(oldres); stb_vorbis_close(v); return 0; }
}
TSF_MEMCPY(res + resNum - n_samples, outputs[0], n_samples * sizeof(float));
}
stb_vorbis_close(v);
*pRes = res; *pResNum = resNum; *pResMax = resMax;
return 1;
}
static int tsf_decode_sf3_samples(const void* rawBuffer, float** pFloatBuffer, unsigned int* pSmplCount, struct tsf_hydra *hydra)
{
const tsf_u8* smplBuffer = (const tsf_u8*)rawBuffer;
tsf_u32 smplLength = *pSmplCount, resNum = 0, resMax = 0, resInitial = (smplLength > 0x100000 ? (smplLength & ~0xFFFFF) : 65536);
float *res = TSF_NULL, *oldres;
int i, shdrLast = hydra->shdrNum - 1, is_sf3 = 0;
for (i = 0; i <= shdrLast; i++)
{
struct tsf_hydra_shdr *shdr = &hydra->shdrs[i];
if (shdr->sampleType & 0x30) // compression flags (sometimes Vorbis flag)
{
const tsf_u8 *pSmpl = smplBuffer + shdr->start, *pSmplEnd = smplBuffer + shdr->end;
if (pSmpl + 4 > pSmplEnd || !TSF_FourCCEquals(pSmpl, "OggS"))
{
shdr->start = shdr->end = shdr->startLoop = shdr->endLoop = 0;
continue;
}
// Fix up sample indices in shdr (end index is set after decoding)
shdr->start = resNum;
shdr->startLoop += resNum;
shdr->endLoop += resNum;
if (!tsf_decode_ogg(pSmpl, pSmplEnd, &res, &resNum, &resMax, resInitial)) { TSF_FREE(res); return 0; }
shdr->end = resNum;
is_sf3 = 1;
}
else // raw PCM sample
{
float *out; short *in = (short*)smplBuffer + resNum, *inEnd; tsf_u32 oldResNum = resNum;
if (is_sf3) // Fix up sample indices in shdr
{
tsf_u32 fix_offset = resNum - shdr->start;
in -= fix_offset;
shdr->start = resNum;
shdr->end += fix_offset;
shdr->startLoop += fix_offset;
shdr->endLoop += fix_offset;
}
inEnd = in + ((shdr->end >= shdr->endLoop ? shdr->end : shdr->endLoop) - resNum);
if (i == shdrLast || (tsf_u8*)inEnd > (smplBuffer + smplLength)) inEnd = (short*)(smplBuffer + smplLength);
if (inEnd <= in) continue;
// expand our output buffer if necessary then convert the PCM data from short to float
resNum += (tsf_u32)(inEnd - in);
if (resNum > resMax)
{
( run in 0.684 second using v1.01-cache-2.11-cpan-6aa56a78535 )