App-MHFS
view release on metacpan or search on metacpan
share/public_html/static/music_worklet_inprogress/decoder/src/mhfs_cl_track.h view on Meta::CPAN
isXing = (memcmp(xing, "ng\0\0", 4) == 0) || (memcmp(xing, "fo\0\0", 4) == 0);
if(isXing)
{
pTrack->vf.fileoffset -= 2;
}
}
if(isXing)
{
const uint8_t *flagsBytes;
const blockvf_error xingFlagsError = blockvf_read_view(&pTrack->vf, 4, &flagsBytes, &pReturnData->needed_offset);
if(xingFlagsError != BLOCKVF_SUCCESS)
{
return mhfs_cl_error_from_blockvf_error(xingFlagsError);
}
const uint32_t xingFlags = unaligned_beu32_to_native(flagsBytes);
if(xingFlags & 0x1)
{
const uint8_t *framesBytes;
const blockvf_error framesError = blockvf_read_view(&pTrack->vf, 4, &framesBytes, &pReturnData->needed_offset);
if(framesError != BLOCKVF_SUCCESS)
{
return mhfs_cl_error_from_blockvf_error(framesError);
}
const uint32_t frames = unaligned_beu32_to_native(framesBytes);
MHFSCLTR_PRINT("xing frames %u\n", frames);
// FIX ME FIX ME we add 1 to mp3frames because the decoder will currently (foolishly) decode the xing mp3frame
mhfs_cl_track_meta_audioinfo_init(&pTrack->meta, (frames + 1) * 1152, sampleRate, channels, MCT_MAI_FLD_BITRATE, 0, bitrate);
if(on_metablock != NULL)
{
on_metablock(context, MHFS_CL_TRACK_M_AUDIOINFO, &pTrack->meta);
}
pTrack->meta_initialized = true;
return MHFS_CL_SUCCESS;
}
return MHFS_CL_ERROR;
}
// check for VBRI
const blockvf_error seekVBRI = blockvf_seek(&pTrack->vf, startoffset+36, blockvf_seek_origin_start);
if(seekVBRI != BLOCKVF_SUCCESS)
{
return mhfs_cl_error_from_blockvf_error(seekVBRI);
}
const uint8_t *vbriMagic;
const blockvf_error vbriMagicError = blockvf_read_view(&pTrack->vf, 4, &vbriMagic, &pReturnData->needed_offset);
if(vbriMagicError != BLOCKVF_SUCCESS)
{
return mhfs_cl_error_from_blockvf_error(vbriMagicError);
}
if(memcmp(vbriMagic, "VBRI", 4) == 0)
{
MHFSCLTR_PRINT("VBRI found\n");
const uint8_t *vbriFields;
const blockvf_error vbriFieldsError = blockvf_read_view(&pTrack->vf, 22, &vbriFields, &pReturnData->needed_offset);
if(vbriFieldsError != BLOCKVF_SUCCESS)
{
return mhfs_cl_error_from_blockvf_error(vbriFieldsError);
}
const uint32_t frames = unaligned_beu32_to_native(&vbriFields[10]);
MHFSCLTR_PRINT("vbri frames %u\n", frames);
// FIX ME FIX ME need to verify pcmframes calculation
mhfs_cl_track_meta_audioinfo_init(&pTrack->meta, (frames + 1) * 1152, sampleRate, channels, MCT_MAI_FLD_BITRATE, 0, bitrate);
if(on_metablock != NULL)
{
on_metablock(context, MHFS_CL_TRACK_M_AUDIOINFO, &pTrack->meta);
}
pTrack->meta_initialized = true;
return MHFS_CL_SUCCESS;
}
// TODO
// ID3 TLEN?
//estimate from bitrate?
return MHFS_CL_ERROR;
}
typedef enum {
MCT_WAVE_FORMAT_PCM = 0x1,
MCT_WAVE_FORMAT_ADPCM = 0x2,
MCT_WAVE_FORMAT_IEEE_FLOAT = 0x3,
MCT_WAVE_FORMAT_ALAW = 0x6,
MCT_WAVE_FORMAT_MULAW = 0x7,
MCT_WAVE_FORMAT_DVI_ADPCM = 0x11,
MCT_WAVE_FORMAT_EXTENSIBLE = 0xFFFE
} mhfs_cl_wav_format;
typedef enum {
MCT_WAVE_CHUNK_FMT = 'f' | ('m' << 8) | ('t' << 16) | (' ' << 24),
MCT_WAVE_CHUNK_DATA = 'd' | ('a' << 8) | ('t' << 16) | ('a' << 24)
} mhfs_cl_riff_chunk_type;
static inline mhfs_cl_error mhfs_cl_wav_read_chunk_header(blockvf *pBlockvf, uint32_t *pNeededOffset, mhfs_cl_riff_chunk_type *pChunkType, uint32_t *pChunkSize)
{
const uint8_t *chunkHeader;
const blockvf_error chunkHeaderError = blockvf_read_view(pBlockvf, 8, &chunkHeader, pNeededOffset);
if(chunkHeaderError != BLOCKVF_SUCCESS)
{
return mhfs_cl_error_from_blockvf_error(chunkHeaderError);
}
*pChunkType = unaligned_leu32_to_native(&chunkHeader[0]);
*pChunkSize = unaligned_leu32_to_native(&chunkHeader[4]);
return MHFS_CL_SUCCESS;
}
static mhfs_cl_error mhfs_cl_track_load_metadata_wav(mhfs_cl_track *pTrack, mhfs_cl_track_return_data *pReturnData, const mhfs_cl_track_on_metablock on_metablock, void *context)
{
{
const uint8_t *wavHeader;
const blockvf_error wavHeaderError = blockvf_read_view(&pTrack->vf, 12, &wavHeader, &pReturnData->needed_offset);
if(wavHeaderError != BLOCKVF_SUCCESS)
{
return mhfs_cl_error_from_blockvf_error(wavHeaderError);
}
if(memcmp(&wavHeader[0], "RIFF", 4) != 0)
{
share/public_html/static/music_worklet_inprogress/decoder/src/mhfs_cl_track.h view on Meta::CPAN
mhfs_cl_track_blockvf_ma_decoder_call_before(pTrack, false);
const ma_result openRes = ma_decoder_init(&mhfs_cl_track_on_read_ma_decoder, &mhfs_cl_track_on_seek_ma_decoder, pTrack, &pTrack->decoderConfig, &pTrack->decoder);
const mhfs_cl_error openBlockRes = mhfs_cl_track_blockvf_ma_decoder_call_after(pTrack, false, pNeededOffset);
if(openBlockRes != MHFS_CL_SUCCESS)
{
if(openRes == MA_SUCCESS) ma_decoder_uninit(&pTrack->decoder);
return openBlockRes;
}
else if(openRes == MA_SUCCESS)
{
pTrack->dec_initialized = true;
return MHFS_CL_SUCCESS;
}
return MHFS_CL_ERROR;
}
static mhfs_cl_error mhfs_cl_track_load_metadata_ma_decoder(mhfs_cl_track *pTrack, mhfs_cl_track_return_data *pReturnData, const mhfs_cl_track_on_metablock on_metablock, void *context)
{
// open the decoder
mhfs_cl_error retval = mhfs_cl_track_open_ma_decoder(pTrack, &pReturnData->needed_offset);
if(retval != MHFS_CL_SUCCESS)
{
return retval;
}
// read and store the metadata
const unsigned savefileoffset = pTrack->vf.fileoffset;
uint64_t totalPCMFrameCount = pTrack->meta.totalPCMFrameCount;
if(pTrack->decoderConfig.encodingFormat != ma_encoding_format_mp3)
{
ma_decoder_get_length_in_pcm_frames(&pTrack->decoder, &totalPCMFrameCount);
}
MHFSCLTR_PRINT("decoder output samplerate %u\n", pTrack->decoder.outputSampleRate);
mhfs_cl_track_meta_audioinfo_init(&pTrack->meta, totalPCMFrameCount, pTrack->decoder.outputSampleRate, pTrack->decoder.outputChannels, MCT_MAI_FLD_EMPTY, 0, 0);
if(on_metablock != NULL)
{
on_metablock(context, MHFS_CL_TRACK_M_AUDIOINFO, &pTrack->meta);
}
if(retval == MHFS_CL_SUCCESS)
{
pTrack->meta_initialized = true;
}
pTrack->vf.fileoffset = savefileoffset;
return retval;
}
static inline ma_encoding_format mhfs_cl_guess_codec(const uint8_t *id, const char *mime, const char *fullfilename)
{
const size_t namelen = strlen(fullfilename);
const char *lastFourChars = (namelen >= 4) ? (fullfilename + namelen - 4) : "";
const uint32_t uMagic = unaligned_beu32_to_native(id);
if(memcmp(id, "fLaC", 4) == 0)
{
return ma_encoding_format_flac;
}
else if(memcmp(id, "RIFF", 4) == 0)
{
return ma_encoding_format_wav;
}
// check mpeg sync and verify the audio version id isn't reserved
else if(((uMagic & 0xFFE00000) == 0xFFE00000) && ((uMagic & 0x00180000) != 0x80000))
{
return ma_encoding_format_mp3;
}
// fallback, attempt to speed up guesses by mime
else if(strcmp(mime, "audio/flac") == 0)
{
return ma_encoding_format_flac;
}
else if((strcmp(mime, "audio/wave") == 0) || (strcmp(mime, "audio/wav") == 0))
{
return ma_encoding_format_wav;
}
else if(strcmp(mime, "audio/mpeg") == 0)
{
return ma_encoding_format_mp3;
}
// fallback, fallback attempt to speed up guesses with file extension
else if(strcmp(lastFourChars, "flac") == 0)
{
return ma_encoding_format_flac;
}
else if(strcmp(lastFourChars, ".wav") == 0)
{
return ma_encoding_format_wav;
}
else if(strcmp(lastFourChars, ".mp3") == 0)
{
return ma_encoding_format_mp3;
}
else
{
MHFSCLTR_PRINT("warning: unable to guess format\n");
return ma_encoding_format_unknown;
}
}
typedef struct {
bool initialized;
mhfs_cl_error res;
uint32_t neededOffset;
} mhfs_cl_track_io_error;
static inline void mhfs_cl_track_io_error_update(mhfs_cl_track_io_error *ioError, const mhfs_cl_error res, const uint32_t neededOffset)
{
if(res != MHFS_CL_NEED_MORE_DATA) return;
if(!ioError->initialized)
{
ioError->initialized = true;
ioError->res = res;
ioError->neededOffset = neededOffset;
}
}
mhfs_cl_error mhfs_cl_track_load_metadata(mhfs_cl_track *pTrack, mhfs_cl_track_return_data *pReturnData, const char *mime, const char *fullfilename, const uint64_t totalPCMFrameCount, const mhfs_cl_track_on_metablock on_metablock, void *context)
{
mhfs_cl_track_return_data rd;
if(pReturnData == NULL) pReturnData = &rd;
// seek past ID3 tags
( run in 1.029 second using v1.01-cache-2.11-cpan-e1769b4cff6 )