Ejemplo n.º 1
0
unsigned int SoundSourceCoreAudio::read(unsigned long size, const SAMPLE *destination) {
    //if (!m_decoder) return 0;
    OSStatus err;
    SAMPLE *destBuffer(const_cast<SAMPLE*>(destination));
    UInt32 numFrames = 0;//(size / 2); /// m_inputFormat.mBytesPerFrame);
    unsigned int totalFramesToRead = size/2;
    unsigned int numFramesRead = 0;
    unsigned int numFramesToRead = totalFramesToRead;

    while (numFramesRead < totalFramesToRead) { //FIXME: Hardcoded 2
    	numFramesToRead = totalFramesToRead - numFramesRead;

		AudioBufferList fillBufList;
		fillBufList.mNumberBuffers = 1; //Decode a single track?
		fillBufList.mBuffers[0].mNumberChannels = m_inputFormat.mChannelsPerFrame;
		fillBufList.mBuffers[0].mDataByteSize = math_min(1024, numFramesToRead*4);//numFramesToRead*sizeof(*destBuffer); // 2 = num bytes per SAMPLE
		fillBufList.mBuffers[0].mData = (void*)(&destBuffer[numFramesRead*2]);

			// client format is always linear PCM - so here we determine how many frames of lpcm
			// we can read/write given our buffer size
		numFrames = numFramesToRead; //This silly variable acts as both a parameter and return value.
		err = ExtAudioFileRead (m_audioFile, &numFrames, &fillBufList);
		//The actual number of frames read also comes back in numFrames.
		//(It's both a parameter to a function and a return value. wat apple?)
		//XThrowIfError (err, "ExtAudioFileRead");
		if (!numFrames) {
				// this is our termination condition
			break;
		}
		numFramesRead += numFrames;
    }
    return numFramesRead*2;
}
Ejemplo n.º 2
0
unsigned int SoundSourceFLAC::read(unsigned long size, const SAMPLE *destination) {
    if (!m_decoder) return 0;
    SAMPLE *destBuffer(const_cast<SAMPLE*>(destination));
    unsigned int samplesWritten = 0;
    unsigned int i = 0;
    while (samplesWritten < size) {
        // if our buffer from libflac is empty (either because we explicitly cleared
        // it or because we've simply used all the samples), ask for a new buffer
        if (m_flacBufferLength == 0) {
            i = 0;
            if (!FLAC__stream_decoder_process_single(m_decoder)) {
                qWarning() << "SSFLAC: decoder_process_single returned false";
                break;
            } else if (m_flacBufferLength == 0) {
                // EOF
                break;
            }
        }
        destBuffer[samplesWritten++] = m_flacBuffer[i++];
        --m_flacBufferLength;
    }
    if (m_flacBufferLength != 0) {
        memcpy(m_leftoverBuffer, &m_flacBuffer[i],
                m_flacBufferLength * sizeof(m_flacBuffer[0])); // safe because leftoverBuffer
                                                               // is as long as flacbuffer
        memcpy(m_flacBuffer, m_leftoverBuffer,
                m_flacBufferLength * sizeof(m_leftoverBuffer[0]));
        // this whole if block could go away if this just used a ring buffer but I'd
        // rather do that after I've gotten off the inital happiness of getting this right,
        // if I see SIGSEGV one more time I'll pop -- bkgood
    }
    return samplesWritten;
}
Ejemplo n.º 3
0
bool CompressStream(Serializer& dest, Deserializer& src)
{
    unsigned srcSize = src.GetSize() - src.GetPosition();
    // Prepend the source and dest. data size in the stream so that we know to buffer & uncompress the right amount
    if (!srcSize)
    {
        dest.WriteUInt(0);
        dest.WriteUInt(0);
        return true;
    }
    
    unsigned maxDestSize = LZ4_compressBound(srcSize);
    SharedArrayPtr<unsigned char> srcBuffer(new unsigned char[srcSize]);
    SharedArrayPtr<unsigned char> destBuffer(new unsigned char[maxDestSize]);
    
    if (src.Read(srcBuffer, srcSize) != srcSize)
        return false;
    
    unsigned destSize = LZ4_compressHC((const char*)srcBuffer.Get(), (char*)destBuffer.Get(), srcSize);
    bool success = true;
    success &= dest.WriteUInt(srcSize);
    success &= dest.WriteUInt(destSize);
    success &= dest.Write(destBuffer, destSize) == destSize;
    return success;
}
Ejemplo n.º 4
0
void Recognizer::run()
{
    // Create audio converter:
    auto converter = ci::audio::dsp::Converter::create( mMonitorNode->getSampleRate(), 16000, mMonitorNode->getNumChannels(), 1, mMonitorNode->getFramesPerBlock() );
    // Create buffer for converted audio:
    ci::audio::Buffer destBuffer( converter->getDestMaxFramesPerBlock(), converter->getDestNumChannels() );

    bool utt_started, in_speech;

    if( ps_start_utt( mDecoder ) < 0 )
        throw std::runtime_error( "Could not start utterance" );

    utt_started = false;

    while( ! mStop ) {
        // Convert buffer:
        std::pair<size_t,size_t> convertResult = converter->convert( &( mMonitorNode->getBuffer() ), &destBuffer );

        // Convert buffer data:
        int16_t* data = new int16_t[ convertResult.second ];
        convertFloatToInt16( destBuffer.getData(), data, convertResult.second );

        // Process buffer:
        ps_process_raw( mDecoder, data, convertResult.second, false, false );

        // Cleanup buffer data:
        delete[] data;

        in_speech = static_cast<bool>( ps_get_in_speech( mDecoder ) );

        if( in_speech && ! utt_started ) {
            utt_started = true;
        }

        if( ! in_speech && utt_started ) {
            // Start new utterance on speech to silence transition:
            ps_end_utt( mDecoder );

            // Pass to handler:
            if( mHandler )
                mHandler->event( mDecoder );

            // Prepare for next utterance:
            if( ps_start_utt( mDecoder ) < 0 )
                throw std::runtime_error( "Could not start utterance" );

            utt_started = false;
        }

        std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
    }
}
int AudioDecoderCoreAudio::read(int size, const SAMPLE *destination) {
    OSStatus err;
    SAMPLE *destBuffer(const_cast<SAMPLE*>(destination));
    unsigned int samplesWritten = 0;
    unsigned int i = 0;
    UInt32 numFrames = 0;
    unsigned int totalFramesToRead = size/2;
    unsigned int numFramesRead = 0;
    unsigned int numFramesToRead = totalFramesToRead;

    while (numFramesRead < totalFramesToRead) { 
    	numFramesToRead = totalFramesToRead - numFramesRead;
    	
		AudioBufferList fillBufList;
		fillBufList.mNumberBuffers = 1; //Decode a single track
        //See CoreAudioTypes.h for definitins of these variables:
		fillBufList.mBuffers[0].mNumberChannels = m_clientFormat.NumberChannels();
		fillBufList.mBuffers[0].mDataByteSize = numFramesToRead*2 * sizeof(SAMPLE);
		fillBufList.mBuffers[0].mData = (void*)(&destBuffer[numFramesRead*2]);
			
        // client format is always linear PCM - so here we determine how many frames of lpcm
        // we can read/write given our buffer size
		numFrames = numFramesToRead; //This silly variable acts as both a parameter and return value.
		err = ExtAudioFileRead (m_audioFile, &numFrames, &fillBufList);
		//The actual number of frames read also comes back in numFrames.
		//(It's both a parameter to a function and a return value. wat apple?)
		//XThrowIfError (err, "ExtAudioFileRead");	
        /*
        if (err != noErr)
        {
            std::cerr << "Error reading samples from file" << std::endl;
            return 0;
        }*/

		if (!numFrames) {
				// this is our termination condition
			break;
		}
		numFramesRead += numFrames;
    }
    
    m_iPositionInSamples += numFramesRead*m_iChannels;

    return numFramesRead*m_iChannels;
}
Ejemplo n.º 6
0
bool DecompressStream(Serializer& dest, Deserializer& src)
{
    if (src.IsEof())
        return false;
    
    unsigned destSize = src.ReadUInt();
    unsigned srcSize = src.ReadUInt();
    if (!srcSize || !destSize)
        return true; // No data
    
    if (srcSize > src.GetSize())
        return false; // Illegal source (packed data) size reported, possibly not valid data
    
    SharedArrayPtr<unsigned char> srcBuffer(new unsigned char[srcSize]);
    SharedArrayPtr<unsigned char> destBuffer(new unsigned char[destSize]);
    
    if (src.Read(srcBuffer, srcSize) != srcSize)
        return false;
    
    LZ4_decompress_fast((const char*)srcBuffer.Get(), (char*)destBuffer.Get(), destSize);
    return dest.Write(destBuffer, destSize) == destSize;
}
unsigned int SoundSourceMediaFoundation::read(unsigned long size,
    const SAMPLE *destination)
{
    if (sDebug) { qDebug() << "read()" << size; }
    SAMPLE *destBuffer(const_cast<SAMPLE*>(destination));
    size_t framesRequested(size / kNumChannels);
    size_t framesNeeded(framesRequested);

    // first, copy frames from leftover buffer IF the leftover buffer is at
    // the correct frame
    if (m_leftoverBufferLength > 0 && m_leftoverBufferPosition == m_nextFrame) {
        copyFrames(destBuffer, &framesNeeded, m_leftoverBuffer,
            m_leftoverBufferLength);
        if (m_leftoverBufferLength > 0) {
            if (framesNeeded != 0) {
                qWarning() << __FILE__ << __LINE__
                           << "WARNING: Expected frames needed to be 0. Abandoning this file.";
                m_dead = true;
            }
            m_leftoverBufferPosition += framesRequested;
        }
    } else {
        // leftoverBuffer already empty or in the wrong position, clear it
        m_leftoverBufferLength = 0;
    }

    while (!m_dead && framesNeeded > 0) {
        HRESULT hr(S_OK);
        DWORD dwFlags(0);
        qint64 timestamp(0);
        IMFSample *pSample(NULL);
        bool error(false); // set to true to break after releasing

        hr = m_pReader->ReadSample(
            MF_SOURCE_READER_FIRST_AUDIO_STREAM, // [in] DWORD dwStreamIndex,
            0,                                   // [in] DWORD dwControlFlags,
            NULL,                                // [out] DWORD *pdwActualStreamIndex,
            &dwFlags,                            // [out] DWORD *pdwStreamFlags,
            &timestamp,                          // [out] LONGLONG *pllTimestamp,
            &pSample);                           // [out] IMFSample **ppSample
        if (FAILED(hr)) {
            if (sDebug) { qDebug() << "ReadSample failed."; }
            break;
        }

        if (sDebug) {
            qDebug() << "ReadSample timestamp:" << timestamp
                     << "frame:" << frameFromMF(timestamp)
                     << "dwflags:" << dwFlags;
        }

        if (dwFlags & MF_SOURCE_READERF_ERROR) {
            // our source reader is now dead, according to the docs
            qWarning() << "SSMF: ReadSample set ERROR, SourceReader is now dead";
            m_dead = true;
            break;
        } else if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM) {
            qDebug() << "SSMF: End of input file.";
            break;
        } else if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) {
            qWarning() << "SSMF: Type change";
            break;
        } else if (pSample == NULL) {
            // generally this will happen when dwFlags contains ENDOFSTREAM,
            // so it'll be caught before now -bkgood
            qWarning() << "SSMF: No sample";
            continue;
        } // we now own a ref to the instance at pSample

        IMFMediaBuffer *pMBuffer(NULL);
        // I know this does at least a memcopy and maybe a malloc, if we have
        // xrun issues with this we might want to look into using
        // IMFSample::GetBufferByIndex (although MS doesn't recommend this)
        if (FAILED(hr = pSample->ConvertToContiguousBuffer(&pMBuffer))) {
            error = true;
            goto releaseSample;
        }
        qint16 *buffer(NULL);
        size_t bufferLength(0);
        hr = pMBuffer->Lock(reinterpret_cast<quint8**>(&buffer), NULL,
            reinterpret_cast<DWORD*>(&bufferLength));
        if (FAILED(hr)) {
            error = true;
            goto releaseMBuffer;
        }
        bufferLength /= (kBitsPerSample / 8 * kNumChannels); // now in frames

        if (m_seeking) {
            qint64 bufferPosition(frameFromMF(timestamp));
            if (sDebug) {
                qDebug() << "While seeking to "
                         << m_nextFrame << "WMF put us at" << bufferPosition;

            }
            if (m_nextFrame < bufferPosition) {
                // Uh oh. We are farther forward than our seek target. Emit
                // silence? We can't seek backwards here.
                SAMPLE* pBufferCurpos = destBuffer +
                        (size - framesNeeded * kNumChannels);
                qint64 offshootFrames = bufferPosition - m_nextFrame;

                // If we can correct this immediately, write zeros and adjust
                // m_nextFrame to pretend it never happened.

                if (offshootFrames <= framesNeeded) {
                    qWarning() << __FILE__ << __LINE__
                               << "Working around inaccurate seeking. Writing silence for"
                               << offshootFrames << "frames";
                    // Set offshootFrames * kNumChannels samples to zero.
                    memset(pBufferCurpos, 0,
                           sizeof(*pBufferCurpos) * offshootFrames *
                           kNumChannels);
                    // Now m_nextFrame == bufferPosition
                    m_nextFrame += offshootFrames;
                    framesNeeded -= offshootFrames;
                } else {
                    // It's more complicated. The buffer we have just decoded is
                    // more than framesNeeded frames away from us. It's too hard
                    // for us to handle this correctly currently, so let's just
                    // try to get on with our lives.
                    m_seeking = false;
                    m_nextFrame = bufferPosition;
                    qWarning() << __FILE__ << __LINE__
                               << "Seek offshoot is too drastic. Cutting losses and pretending the current decoded audio buffer is the right seek point.";
                }
            }

            if (m_nextFrame >= bufferPosition &&
                m_nextFrame < bufferPosition + bufferLength) {
                // m_nextFrame is in this buffer.
                buffer += (m_nextFrame - bufferPosition) * kNumChannels;
                bufferLength -= m_nextFrame - bufferPosition;
                m_seeking = false;
            } else {
                // we need to keep going forward
                goto releaseRawBuffer;
            }
        }

        // If the bufferLength is larger than the leftover buffer, re-allocate
        // it with 2x the space.
        if (bufferLength * kNumChannels > m_leftoverBufferSize) {
            int newSize = m_leftoverBufferSize;

            while (newSize < bufferLength * kNumChannels) {
                newSize *= 2;
            }
            qint16* newBuffer = new qint16[newSize];
            memcpy(newBuffer, m_leftoverBuffer,
                   sizeof(m_leftoverBuffer[0]) * m_leftoverBufferSize);
            delete [] m_leftoverBuffer;
            m_leftoverBuffer = newBuffer;
            m_leftoverBufferSize = newSize;
        }
        copyFrames(destBuffer + (size - framesNeeded * kNumChannels),
            &framesNeeded, buffer, bufferLength);

releaseRawBuffer:
        hr = pMBuffer->Unlock();
        // I'm ignoring this, MSDN for IMFMediaBuffer::Unlock stipulates
        // nothing about the state of the instance if this fails so might as
        // well just let it be released.
        //if (FAILED(hr)) break;
releaseMBuffer:
        safeRelease(&pMBuffer);
releaseSample:
        safeRelease(&pSample);
        if (error) break;
    }

    m_nextFrame += framesRequested - framesNeeded;
    if (m_leftoverBufferLength > 0) {
        if (framesNeeded != 0) {
            qWarning() << __FILE__ << __LINE__
                       << "WARNING: Expected frames needed to be 0. Abandoning this file.";
            m_dead = true;
        }
        m_leftoverBufferPosition = m_nextFrame;
    }
    long samples_read = size - framesNeeded * kNumChannels;
    m_iCurrentPosition += samples_read;
    if (sDebug) { qDebug() << "read()" << size << "returning" << samples_read; }
    return samples_read;
}