All pastes #182436 Raw Edit

Something

public cpp v1 · immutable
#182436 ·published 2006-09-26 00:40 UTC
rendered paste body
//==============================================================================#define formatName                          TRANS("Ogg-Vorbis file")static const tchar* const extensions[] =    { T(".ogg"), 0 };// photon#define READS_UNTIL_REDUCTION 50//==============================================================================class OggReader : public AudioFormatReader{    OggVorbis_File ovFile;    ov_callbacks callbacks;    AudioSampleBuffer reservoir;    int reservoirStart, samplesInReservoir;    int readsUntilReduction; // photon    int reservoirWriteIndex; // photon    public:    //==============================================================================    OggReader (InputStream* const inp)        : AudioFormatReader (inp, formatName),          reservoir (2, 2048),          reservoirStart (0),          samplesInReservoir (0),          readsUntilReduction (READS_UNTIL_REDUCTION), // photon          reservoirWriteIndex (0) // photon    {        sampleRate = 0;        usesFloatingPointData = true;        callbacks.read_func = &oggReadCallback;        callbacks.seek_func = &oggSeekCallback;        callbacks.close_func = &oggCloseCallback;        callbacks.tell_func = &oggTellCallback;        const int err = ov_open_callbacks (input, &ovFile, 0, 0, callbacks);        if (err == 0)        {            vorbis_info* info = ov_info (&ovFile, -1);            lengthInSamples = (uint32) ov_pcm_total (&ovFile, -1);            numChannels = info->channels;            bitsPerSample = 16;            sampleRate = info->rate;            reservoir.setSize (numChannels,                               (int) jmin (lengthInSamples, (int64) reservoir.getNumSamples()));        }    }    ~OggReader()    {        ov_clear (&ovFile);    }    //==============================================================================        // photon    bool read (int** destSamples,               int64 startSampleInFile,               int numSamples)    {        // out-of-bounds read, fillin zeros        if (startSampleInFile > lengthInSamples || startSampleInFile < 0)        {            for (uint32 i = 0; i < numChannels && destSamples[i]; i++)                zeromem(destSamples[i], sizeof(float) * numSamples);                        return true;        }                // resize reservoir        int possibleNewReservoirSize = (numSamples + 1024 - 1 - ((numSamples - 1) % 1024)) + 1024;                if (possibleNewReservoirSize > reservoir.getNumSamples()            || (possibleNewReservoirSize < reservoir.getNumSamples() / 2 && !readsUntilReduction))        {            // only resize reservoir if it needs to be larger, or if the last             // READS_UNTIL_REDUCTION reads allow a size half as big as the current one.            // this way single small reads wont trigger a reduction            reservoir.setSize(numChannels, possibleNewReservoirSize);                        ov_pcm_seek (&ovFile, startSampleInFile);                        reservoirStart = startSampleInFile;            samplesInReservoir = 0;            reservoirWriteIndex = 0;            readsUntilReduction = READS_UNTIL_REDUCTION;        }        else if (possibleNewReservoirSize < reservoir.getNumSamples() / 2)            --readsUntilReduction;        else            readsUntilReduction = READS_UNTIL_REDUCTION;                // seek        if (startSampleInFile != reservoirStart)        {            ov_pcm_seek (&ovFile, startSampleInFile);                        reservoirStart = startSampleInFile;            samplesInReservoir = 0;            reservoirWriteIndex = 0;        }                // decode        if (samplesInReservoir < numSamples)        {            while (samplesInReservoir < reservoir.getNumSamples())            {                float** samples = NULL;                int numToRead = reservoir.getNumSamples() - samplesInReservoir;                int numToWrite = ov_read_float (&ovFile, &samples, numToRead, 0);                int numToWriteAsFirstBlock = jmin (reservoir.getNumSamples() - reservoirWriteIndex, numToWrite);                                if (! numToWrite)                    break;                                for (int i = jmin (numChannels, reservoir.getNumChannels()); --i >= 0;)                {                       memcpy (reservoir.getSampleData (i, reservoirWriteIndex),                            samples[i],                            sizeof(float) * numToWriteAsFirstBlock);                                        if (numToWrite > numToWriteAsFirstBlock)                    {                            memcpy (reservoir.getSampleData (i, 0),                                samples[i] + numToWriteAsFirstBlock,                                sizeof(float) * (numToWrite - numToWriteAsFirstBlock));                    }                }                                reservoirWriteIndex = (reservoirWriteIndex + numToWrite) % reservoir.getNumSamples();                samplesInReservoir += numToWrite;            }        }                // read        if (numSamples > 0)        {            int numToRead = jmin(numSamples, samplesInReservoir);            int readIndex = reservoirWriteIndex - samplesInReservoir;                        if (readIndex < 0)                readIndex += reservoir.getNumSamples();                            int numToReadAsFirstBlock = jmin(reservoir.getNumSamples() - readIndex, numToRead);                        for (uint32 i = 0; i < numChannels && destSamples[i]; ++i)            {                int channelIndex = jmin (i, reservoir.getNumChannels());                                memcpy(destSamples[i],                       reservoir.getSampleData(channelIndex, readIndex),                       sizeof(float) * numToReadAsFirstBlock);                                if (numToRead > numToReadAsFirstBlock)                {                        memcpy (destSamples[i] + numToReadAsFirstBlock,                            reservoir.getSampleData(channelIndex, 0),                            sizeof(float) * (numToRead - numToReadAsFirstBlock));                }                                if (numSamples > numToRead)                    zeromem (destSamples[i] + numToRead, sizeof(float) * (numSamples - numToRead));            }                        reservoirStart += numToRead;             samplesInReservoir -= numToRead;        }        return true;    }    //==============================================================================    static size_t oggReadCallback (void* ptr, size_t size, size_t nmemb, void* datasource)    {        return (size_t) (((InputStream*) datasource)->read (ptr, (int) (size * nmemb)) / size);    }    static int oggSeekCallback (void* datasource, ogg_int64_t offset, int whence)    {        InputStream* const in = (InputStream*) datasource;        if (whence == SEEK_CUR)            offset += in->getPosition();        else if (whence == SEEK_END)            offset += in->getTotalLength();        in->setPosition (offset);        return 0;    }    static int oggCloseCallback (void*)    {        return 0;    }    static long oggTellCallback (void* datasource)    {        return (long) ((InputStream*) datasource)->getPosition();    }    juce_UseDebuggingNewOperator};