Example #1
0
        public unsafe int DecodePCM(SoundSample sample, int sampleOffset44k, int sampleCount44k, float *dest)
        {
            lastFormat = WAVE_FORMAT_TAG.PCM;
            lastSample = sample;

            var shift        = 22050 / sample.objectInfo.nSamplesPerSec;
            var sampleOffset = sampleOffset44k >> shift;
            var sampleCount  = sampleCount44k >> shift;

            if (sample.nonCacheData == null)
            {
                Debug.Assert(false); failed = true; return(0);
            }                                                                                   // this should never happen ( note: I've seen that happen with the main thread down in idGameLocal::MapClear clearing entities - TTimo )
            if (!sample.FetchFromCache(sampleOffset * sizeof(short), out var first, out var pos, out var size, false))
            {
                failed = true; return(0);
            }

            var readSamples = size - pos < sampleCount * sizeof(short) ? (size - pos) / sizeof(short) : sampleCount;

            // duplicate samples for 44kHz output
            fixed(byte *_ = &first.v[first.o + pos]) Simd.UpSamplePCMTo44kHz(dest, (short *)_, readSamples, sample.objectInfo.nSamplesPerSec, sample.objectInfo.nChannels);

            return(readSamples << shift);
        }
Example #2
0
 public void Clear()
 {
     failed           = false;
     lastFormat       = WAVE_FORMAT_TAG.PCM;
     lastSample       = null;
     lastSampleOffset = 0;
     lastDecodeTime   = 0;
 }
Example #3
0
        public unsafe int DecodeOGG(SoundSample sample, int sampleOffset44k, int sampleCount44k, float *dest)
        {
            int readSamples, totalSamples;

            var shift        = 22050 / sample.objectInfo.nSamplesPerSec;
            var sampleOffset = sampleOffset44k >> shift;
            var sampleCount  = sampleCount44k >> shift;

            // open OGG file if not yet opened
            if (lastSample == null)
            {
                // make sure there is enough space for another decoder
                if (ISampleDecoder.decoderMemoryAllocator.FreeBlockMemory < ISampleDecoder.MIN_OGGVORBIS_MEMORY)
                {
                    return(0);
                }

                if (sample.nonCacheData == null)
                {
                    Debug.Assert(false); failed = true; return(0);
                }                                                                                  // this should never happen
                file.SetData(sample.nonCacheData, sample.objectMemSize);
                if (OggVorbis.ov_openFile(file, ogg) < 0)
                {
                    failed = true; return(0);
                }
                lastFormat = WAVE_FORMAT_TAG.OGG;
                lastSample = sample;
            }

            // seek to the right offset if necessary
            if (sampleOffset != lastSampleOffset && ov_pcm_seek(ogg, sampleOffset / sample.objectInfo.nChannels) != 0)
            {
                failed = true; return(0);
            }

            lastSampleOffset = sampleOffset;

            // decode OGG samples
            totalSamples = sampleCount;
            readSamples  = 0;
            do
            {
                float **samples;
                var     ret = (int)ov_read_float(ogg, &samples, totalSamples / sample.objectInfo.nChannels, null);
                if (ret == 0)
                {
                    failed = true; break;
                }
                if (ret < 0)
                {
                    failed = true; return(0);
                }
                ret *= sample.objectInfo.nChannels;

                Simd.UpSampleOGGTo44kHz(dest + (readSamples << shift), samples, ret, sample.objectInfo.nSamplesPerSec, sample.objectInfo.nChannels);

                readSamples  += ret;
                totalSamples -= ret;
            } while (totalSamples > 0);

            lastSampleOffset += readSamples;

            return(readSamples << shift);
        }