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

    {
        *pNeededOffset = pTrack->vfData.extradata;
        if(bRestoreDecoder)
        {
            mhfs_cl_track_allocs_restore(pTrack);
        }
    }
    return mhfs_cl_error_from_blockvf_error(pTrack->vfData.code);
}

static mhfs_cl_error mhfs_cl_track_open_ma_decoder(mhfs_cl_track *pTrack, uint32_t *pNeededOffset)
{
    pTrack->vf.fileoffset = 0;
    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
    pTrack->vf.fileoffset = 0;
    const uint8_t *id;
    for(;;)
    {
        const blockvf_error idError = blockvf_read_view(&pTrack->vf, 4, &id, &pReturnData->needed_offset);
        if(idError != BLOCKVF_SUCCESS)
        {
            return mhfs_cl_error_from_blockvf_error(idError);
        }
        MHFSCLTR_PRINT("uMagic %X %X %X %X @ 0x%X\n", id[0], id[1], id[2], id[3], pTrack->vf.fileoffset-4);
        if(memcmp(id, "ID3", 3) != 0) break;
        pTrack->vf.fileoffset--;
        uint16_t id3version;
        uint8_t flags;
        uint32_t tagSize;
        const mhfs_cl_error parseError = mhfs_cl_parse_id3_header_after_magic(&pTrack->vf, &pReturnData->needed_offset, &id3version, &flags, &tagSize);
        if(parseError != MHFS_CL_SUCCESS)
        {
            return parseError;
        }
        if(BLOCKVF_SUCCESS != blockvf_seek(&pTrack->vf, tagSize, blockvf_seek_origin_current))
        {
            return MHFS_CL_ERROR;
        }
    }
    pTrack->afterID3Offset = pTrack->vf.fileoffset - 4;

    // attempt to guess the codec to determine what codec to try first
    ma_encoding_format encFmt;
    if(pTrack->decoderConfig.encodingFormat == ma_encoding_format_unknown)
    {
        encFmt = mhfs_cl_guess_codec(id, mime, fullfilename);
    }
    else
    {
        encFmt = pTrack->decoderConfig.encodingFormat;
    }
    ma_encoding_format tryorder[] = { ma_encoding_format_flac, ma_encoding_format_mp3, ma_encoding_format_wav};
    const unsigned max_try_count = sizeof(tryorder) / sizeof(tryorder[0]);
    if(encFmt == ma_encoding_format_mp3)
    {
        mhfs_cl_track_swap_tryorder(&tryorder[DAF_MP3], &tryorder[0]);
    }
    else if(encFmt == ma_encoding_format_wav)
    {
        mhfs_cl_track_swap_tryorder(&tryorder[DAF_WAV], &tryorder[0]);
    }

    // set this as a fallback
    pTrack->meta.totalPCMFrameCount = totalPCMFrameCount;

    // try the various codecs
    mhfs_cl_track_io_error ioError = {
        .initialized = false
    };
    for(unsigned i = 0; i < max_try_count; i++)
    {
        pTrack->decoderConfig.encodingFormat = tryorder[i];
        pTrack->vf.fileoffset = pTrack->afterID3Offset;

        // try loading via our methods
        mhfs_cl_track_return_data temprd;
        if(pTrack->decoderConfig.encodingFormat == ma_encoding_format_flac)
        {
            const mhfs_cl_error retval = mhfs_cl_track_load_metadata_flac(pTrack, &temprd, on_metablock, context);
            if(retval == MHFS_CL_SUCCESS)
            {
                return retval;
            }
            mhfs_cl_track_io_error_update(&ioError, retval, temprd.needed_offset);
        }
        else if(pTrack->decoderConfig.encodingFormat == ma_encoding_format_wav)
        {
            const mhfs_cl_error retval = mhfs_cl_track_load_metadata_wav(pTrack, &temprd, on_metablock, context);
            if(retval == MHFS_CL_SUCCESS)
            {
                return retval;
            }
            mhfs_cl_track_io_error_update(&ioError, retval, temprd.needed_offset);
        }
        else if(pTrack->decoderConfig.encodingFormat == ma_encoding_format_mp3)
        {
            const mhfs_cl_error retval = mhfs_cl_track_load_metadata_mp3(pTrack, &temprd, on_metablock, context);
            if(retval == MHFS_CL_SUCCESS)
            {
                return retval;
            }
            mhfs_cl_track_io_error_update(&ioError, retval, temprd.needed_offset);
        }

        // try loading via ma_decoder
        const mhfs_cl_error retval = mhfs_cl_track_load_metadata_ma_decoder(pTrack, &temprd, on_metablock, context);



( run in 2.627 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )