📄 pa_unix_oss.c
字号:
{ 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 + -