⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pa_unix_oss.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 3 页
字号:
    {        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &ossHostApi->callbackStreamInterface, streamCallback, userData );    }    else    {        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &ossHostApi->blockingStreamInterface, streamCallback, userData );    }        stream->streamRepresentation.streamInfo.inputLatency = 0.;    stream->streamRepresentation.streamInfo.outputLatency = 0.;    if (inputChannelCount > 0) {        if (ioctl( deviceHandle, SNDCTL_DSP_GETISPACE, &bufinfo) == 0)            stream->streamRepresentation.streamInfo.inputLatency =                (bufinfo.fragsize * bufinfo.fragstotal) / sampleRate;    }    if (outputChannelCount > 0) {        if (ioctl( deviceHandle, SNDCTL_DSP_GETOSPACE, &bufinfo) == 0)            stream->streamRepresentation.streamInfo.outputLatency =                (bufinfo.fragsize * bufinfo.fragstotal) / sampleRate;    }        stream->streamRepresentation.streamInfo.sampleRate = sampleRate;    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );    /* we assume a fixed host buffer size in this example, but the buffer processor        can also support bounded and unknown host buffer sizes by passing         paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of        paUtilFixedHostBufferSize below. */            result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,              inputChannelCount, inputSampleFormat, hostInputSampleFormat,              outputChannelCount, outputSampleFormat, hostOutputSampleFormat,              sampleRate, streamFlags, framesPerBuffer,              framesPerHostBuffer, paUtilFixedHostBufferSize,              streamCallback, userData );    if( result != paNoError )        goto error;    stream->framesPerHostCallback = framesPerHostBuffer;    stream->stopSoon = 0;    stream->stopNow = 0;    stream->isActive = 0;    stream->thread = 0;    stream->lastPosPtr = 0;    stream->lastStreamBytes = 0;    stream->sampleRate = sampleRate;    stream->framesProcessed = 0;    stream->deviceHandle = deviceHandle;    if (inputChannelCount > 0)        stream->inputBuffer = PaUtil_AllocateMemory( 2 * framesPerHostBuffer * inputChannelCount );    else        stream->inputBuffer = NULL;    if (outputChannelCount > 0)        stream->outputBuffer = PaUtil_AllocateMemory( 2 * framesPerHostBuffer * outputChannelCount );    else        stream->outputBuffer = NULL;    stream->inputChannelCount = inputChannelCount;    stream->outputChannelCount = outputChannelCount;    *s = (PaStream*)stream;    result = paNoError;    return result;error:    if( stream )        PaUtil_FreeMemory( stream );    if( deviceHandle )        close( deviceHandle );    return result;}static void *PaOSS_AudioThreadProc(void *userData){    PaOSSStream *stream = (PaOSSStream*)userData;    DBUG(("PaOSS AudioThread: %d in, %d out\n", stream->inputChannelCount, stream->outputChannelCount));    while( (stream->stopNow == 0) && (stream->stopSoon == 0) ) {        PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* TODO: IMPLEMENT ME */        int callbackResult;        unsigned long framesProcessed;        int bytesRequested;        int bytesRead, bytesWritten;        int delta;        int result;        count_info info;        PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );            PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,                0 /* @todo pass underflow/overflow flags when necessary */ );                /*          depending on whether the host buffers are interleaved, non-interleaved          or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),          PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.        */        if ( stream->inputChannelCount > 0 )        {            bytesRequested = stream->framesPerHostCallback * 2 * stream->inputChannelCount;            bytesRead = read( stream->deviceHandle, stream->inputBuffer, bytesRequested );                        PaUtil_SetInputFrameCount( &stream->bufferProcessor, bytesRead/(2*stream->inputChannelCount));            PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,                                                0, /* first channel of inputBuffer is channel 0 */                                                stream->inputBuffer,                                                0 ); /* 0 - use inputChannelCount passed to init buffer processor */        }        if ( stream->outputChannelCount > 0 )        {           PaUtil_SetOutputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );           PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,                                                0, /* first channel of outputBuffer is channel 0 */                                                stream->outputBuffer,                                                0 ); /* 0 - use outputChannelCount passed to init buffer processor */        }        callbackResult = paContinue;        framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );        PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );                if( callbackResult == paContinue )        {           /* nothing special to do */        }        else if( callbackResult == paAbort )        {            /* once finished, call the finished callback */            if( stream->streamRepresentation.streamFinishedCallback != 0 )                stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );            return NULL; /* return from the loop */        }        else if ( callbackResult == paComplete )        {            /* User callback has asked us to stop with paComplete or other non-zero value */                       /* once finished, call the finished callback */            if( stream->streamRepresentation.streamFinishedCallback != 0 )                stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );            stream->stopSoon = 1;        }        if ( stream->outputChannelCount > 0 ) {            /* write output samples AFTER we've checked the callback result code */            bytesRequested = stream->framesPerHostCallback * 2 * stream->outputChannelCount;            bytesWritten = write( stream->deviceHandle, stream->outputBuffer, bytesRequested );            /* TODO: handle bytesWritten != bytesRequested (slippage?) */        }        /* Update current stream time (using a double so that           we don't wrap around like info.bytes does) */        if( stream->outputChannelCount > 0 )            result = ioctl( stream->deviceHandle, SNDCTL_DSP_GETOPTR, &info);        else            result = ioctl( stream->deviceHandle, SNDCTL_DSP_GETIPTR, &info);        if (result == 0) {            delta = ( info.bytes - stream->lastPosPtr ) & 0x000FFFFF;            stream->lastStreamBytes += delta;            stream->lastPosPtr = info.bytes;        }        stream->framesProcessed += stream->framesPerHostCallback;    }    return NULL;}/*    When CloseStream() is called, the multi-api layer ensures that    the stream has already been stopped or aborted.*/static PaError CloseStream( PaStream* s ){    PaError result = paNoError;    PaOSSStream *stream = (PaOSSStream*)s;    close(stream->deviceHandle);    if ( stream->inputBuffer )        PaUtil_FreeMemory( stream->inputBuffer );    if ( stream->outputBuffer )        PaUtil_FreeMemory( stream->outputBuffer );    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );    PaUtil_FreeMemory( stream );    return result;}static PaError StartStream( PaStream *s ){    PaError result = paNoError;    PaOSSStream *stream = (PaOSSStream*)s;    int presult;    stream->isActive = 1;    stream->lastPosPtr = 0;    stream->lastStreamBytes = 0;    stream->framesProcessed = 0;    DBUG(("PaOSS StartStream\n"));    /* only use the thread for callback streams */    if( stream->bufferProcessor.streamCallback ) {            presult = pthread_create(&stream->thread,                             NULL /*pthread_attr_t * attr*/,                             (void*)PaOSS_AudioThreadProc, (void *)stream);    }        return result;}static PaError StopStream( PaStream *s ){    PaError result = paNoError;    PaOSSStream *stream = (PaOSSStream*)s;    stream->stopSoon = 1;    /* only use the thread for callback streams */    if( stream->bufferProcessor.streamCallback )        pthread_join( stream->thread, NULL );    stream->stopSoon = 0;    stream->stopNow = 0;    stream->isActive = 0;    DBUG(("PaOSS StopStream: Stopped stream\n"));    return result;}static PaError AbortStream( PaStream *s ){    PaError result = paNoError;    PaOSSStream *stream = (PaOSSStream*)s;    stream->stopNow = 1;    /* only use the thread for callback streams */    if( stream->bufferProcessor.streamCallback )        pthread_join( stream->thread, NULL );    stream->stopSoon = 0;    stream->stopNow = 0;    stream->isActive = 0;    DBUG(("PaOSS AbortStream: Stopped stream\n"));    return result;}static PaError IsStreamStopped( PaStream *s ){    PaOSSStream *stream = (PaOSSStream*)s;    return (!stream->isActive);}static PaError IsStreamActive( PaStream *s ){    PaOSSStream *stream = (PaOSSStream*)s;    return (stream->isActive);}static PaTime GetStreamTime( PaStream *s ){    PaOSSStream *stream = (PaOSSStream*)s;    count_info info;    int delta;    if( stream->outputChannelCount > 0 ) {        if (ioctl( stream->deviceHandle, SNDCTL_DSP_GETOPTR, &info) == 0) {            delta = ( info.bytes - stream->lastPosPtr ) & 0x000FFFFF;            return ( stream->lastStreamBytes + delta) / ( stream->outputChannelCount * 2 ) / stream->sampleRate;        }    }    else {        if (ioctl( stream->deviceHandle, SNDCTL_DSP_GETIPTR, &info) == 0) {            delta = (info.bytes - stream->lastPosPtr) & 0x000FFFFF;            return ( stream->lastStreamBytes + delta) / ( stream->inputChannelCount * 2 ) / stream->sampleRate;        }    }    /* the ioctl failed, but we can still give a coarse estimate */    return stream->framesProcessed / stream->sampleRate;}static double GetStreamCpuLoad( PaStream* s ){    PaOSSStream *stream = (PaOSSStream*)s;    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );}/*    As separate stream interfaces are used for blocking and callback    streams, the following functions can be guaranteed to only be called    for blocking streams.*/static PaError ReadStream( PaStream* s,                           void *buffer,                           unsigned long frames ){    PaOSSStream *stream = (PaOSSStream*)s;    int bytesRequested, bytesRead;    bytesRequested = frames * 2 * stream->inputChannelCount;    bytesRead = read( stream->deviceHandle, stream->inputBuffer, bytesRequested );    if ( bytesRequested != bytesRead )        return paUnanticipatedHostError;    else        return paNoError;}static PaError WriteStream( PaStream* s,                            void *buffer,                            unsigned long frames ){    PaOSSStream *stream = (PaOSSStream*)s;    int bytesRequested, bytesWritten;    bytesRequested = frames * 2 * stream->outputChannelCount;    bytesWritten = write( stream->deviceHandle, buffer, bytesRequested );    if ( bytesRequested != bytesWritten )        return paUnanticipatedHostError;    else        return paNoError;}static signed long GetStreamReadAvailable( PaStream* s ){    PaOSSStream *stream = (PaOSSStream*)s;    audio_buf_info info;    if ( ioctl(stream->deviceHandle, SNDCTL_DSP_GETISPACE, &info) == 0)    {        int bytesAvailable = info.fragments * info.fragsize;        return ( bytesAvailable / 2 / stream->inputChannelCount );    }    else        return 0; /* TODO: is this right for "don't know"? */}static signed long GetStreamWriteAvailable( PaStream* s ){    PaOSSStream *stream = (PaOSSStream*)s;    audio_buf_info info;    if ( ioctl(stream->deviceHandle, SNDCTL_DSP_GETOSPACE, &info) == 0)    {        int bytesAvailable = info.fragments * info.fragsize;        return ( bytesAvailable / 2 / stream->outputChannelCount );    }    else        return 0; /* TODO: is this right for "don't know"? */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -