如何解决pa_devs.c 检测设备但其他代码没有
我目前正在尝试使以下代码工作,但是当尝试使用 portaudio 访问设备时 我使用的是 linux 计算机,卡使用 ALSA。并且两个代码都使用相同版本的portaudio
下面的代码是 pa_dev.c 是与 portaudio 一起提供的。此代码可以访问设备,并打印设备:
/** @file pa_devs.c
@ingroup examples_src
@brief List available devices,including device information.
@author Phil Burk http://www.softsynth.com
@note Define PA_USE_ASIO=0 to compile this code on Windows without
ASIO support.
*/
/*
* $Id: pa_devs.c 1752 2011-09-08 03:21:55Z philburk $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted,free of charge,to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"),to deal in the Software without restriction,* including without limitation the rights to use,copy,modify,merge,* publish,distribute,sublicense,and/or sell copies of the Software,* and to permit persons to whom the Software is furnished to do so,* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,* EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY,fitness FOR A PARTIculaR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR copYRIGHT HOLDERS BE LIABLE FOR
* ANY CLaim,damAGES OR OTHER LIABILITY,WHETHER IN AN ACTION OF
* CONTRACT,TORT OR OTHERWISE,ARISING FROM,OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#ifdef WIN32
#if PA_USE_ASIO
#include "pa_asio.h"
#endif
#endif
/*******************************************************************/
static void PrintSupportedStandardSampleRates(
const PaStreamParameters *inputParameters,const PaStreamParameters *outputParameters )
{
static double standardSampleRates[] = {
8000.0,9600.0,11025.0,12000.0,16000.0,22050.0,24000.0,32000.0,44100.0,48000.0,88200.0,96000.0,192000.0,-1 /* negative terminated list */
};
int i,printCount;
PaError err;
printCount = 0;
for( i=0; standardSampleRates[i] > 0; i++ )
{
err = Pa_IsFormatSupported( inputParameters,outputParameters,standardSampleRates[i] );
if( err == paFormatIsSupported )
{
if( printCount == 0 )
{
printf( "\t%8.2f",standardSampleRates[i] );
printCount = 1;
}
else if( printCount == 4 )
{
printf( ",\n\t%8.2f",standardSampleRates[i] );
printCount = 1;
}
else
{
printf( ",%8.2f",standardSampleRates[i] );
++printCount;
}
}
}
if( !printCount )
printf( "None\n" );
else
printf( "\n" );
}
/*******************************************************************/
int main(void);
int main(void)
{
int i,numDevices,defaultdisplayed;
const PaDeviceInfo *deviceInfo;
PaStreamParameters inputParameters,outputParameters;
PaError err;
Pa_Initialize();
printf( "PortAudio version number = %d\nPortAudio version text = '%s'\n",Pa_GetVersion(),Pa_GetVersionText() );
numDevices = Pa_GetDeviceCount();
if( numDevices < 0 )
{
printf( "ERROR: Pa_GetDeviceCount returned 0x%x\n",numDevices );
err = numDevices;
goto error;
}
printf( "Number of devices = %d\n",numDevices );
for( i=0; i<numDevices; i++ )
{
deviceInfo = Pa_GetDeviceInfo( i );
printf( "--------------------------------------- device #%d\n",i );
/* Mark global and API specific default devices */
defaultdisplayed = 0;
if( i == Pa_GetDefaultInputDevice() )
{
printf( "[ Default Input" );
defaultdisplayed = 1;
}
else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultInputDevice )
{
const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi );
printf( "[ Default %s Input",hostInfo->name );
defaultdisplayed = 1;
}
if( i == Pa_GetDefaultOutputDevice() )
{
printf( (defaultdisplayed ? "," : "[") );
printf( " Default Output" );
defaultdisplayed = 1;
}
else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultOutputDevice )
{
const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi );
printf( (defaultdisplayed ? "," : "[") );
printf( " Default %s Output",hostInfo->name );
defaultdisplayed = 1;
}
if( defaultdisplayed )
printf( " ]\n" );
/* print device info fields */
printf( "Name = %s\n",deviceInfo->name );
printf( "Host API = %s\n",Pa_GetHostApiInfo( deviceInfo->hostApi )->name );
printf( "Max inputs = %d",deviceInfo->maxInputChannels );
printf( ",Max outputs = %d\n",deviceInfo->maxOutputChannels );
printf( "Default low input latency = %8.4f\n",deviceInfo->defaultLowInputLatency );
printf( "Default low output latency = %8.4f\n",deviceInfo->defaultLowOutputLatency );
printf( "Default high input latency = %8.4f\n",deviceInfo->defaultHighInputLatency );
printf( "Default high output latency = %8.4f\n",deviceInfo->defaultHighOutputLatency );
#ifdef WIN32
#if PA_USE_ASIO
/* ASIO specific latency information */
if( Pa_GetHostApiInfo( deviceInfo->hostApi )->type == paASIO ){
long minLatency,maxLatency,preferredLatency,granularity;
err = PaAsio_GetAvailableLatencyValues( i,&minLatency,&maxLatency,&preferredLatency,&granularity );
printf( "ASIO minimum buffer size = %ld\n",minLatency );
printf( "ASIO maximum buffer size = %ld\n",maxLatency );
printf( "ASIO preferred buffer size = %ld\n",preferredLatency );
if( granularity == -1 )
printf( "ASIO buffer granularity = power of 2\n" );
else
printf( "ASIO buffer granularity = %ld\n",granularity );
}
#endif /* PA_USE_ASIO */
#endif /* WIN32 */
printf( "Default sample rate = %8.2f\n",deviceInfo->defaultSampleRate );
/* poll for standard sample rates */
inputParameters.device = i;
inputParameters.channelCount = deviceInfo->maxInputChannels;
inputParameters.sampleFormat = paInt16;
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
inputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.device = i;
outputParameters.channelCount = deviceInfo->maxOutputChannels;
outputParameters.sampleFormat = paInt16;
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
outputParameters.hostApiSpecificStreamInfo = NULL;
if( inputParameters.channelCount > 0 )
{
printf("Supported standard sample rates\n for half-duplex 16 bit %d channel input = \n",inputParameters.channelCount );
PrintSupportedStandardSampleRates( &inputParameters,NULL );
}
if( outputParameters.channelCount > 0 )
{
printf("Supported standard sample rates\n for half-duplex 16 bit %d channel output = \n",outputParameters.channelCount );
PrintSupportedStandardSampleRates( NULL,&outputParameters );
}
if( inputParameters.channelCount > 0 && outputParameters.channelCount > 0 )
{
printf("Supported standard sample rates\n for full-duplex 16 bit %d channel input,%d channel output = \n",inputParameters.channelCount,outputParameters.channelCount );
PrintSupportedStandardSampleRates( &inputParameters,&outputParameters );
}
}
Pa_Terminate();
printf("----------------------------------------------\n");
return 0;
error:
Pa_Terminate();
fprintf( stderr,"An error occured while using the portaudio stream\n" );
fprintf( stderr,"Error number: %d\n",err );
fprintf( stderr,"Error message: %s\n",Pa_GetErrorText( err ) );
return err;
}
但是,当我从以下代码调用函数 Pa_GetDeviceCount() 和 Pa_GetDeviceInfo() 时,portaudio 检测到 0 设备并给我消息“设备不可用”
// online/online-audio-source.cc
// copyright 2012 Cisco Systems (author: Matthias Paulik)
// Modifications to the original contribution by Cisco Systems made by:
// Vassil Panayotov
// See ../../copYING for clarification regarding multiple authors
//
// Licensed under the Apache License,Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND,EITHER EXPRESS OR IMPLIED,INCLUDING WITHOUT LIMITATION ANY IMPLIED
// WARRANTIES OR CONDITIONS OF TITLE,fitness FOR A PARTIculaR PURPOSE,// MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.
#include <algorithm>
#include <cmath>
#include <vector>
#ifndef KALDI_NO_PORTAUdio
#include "base/timer.h"
#endif // KALDI_NO_PORTAUdio
#include "online-audio-source.h"
namespace kaldi {
#ifndef KALDI_NO_PORTAUdio
// The actual PortAudio callback - delegates to OnlinePaSource->Callback()
int PaCallback(const void *input,void *output,long unsigned frame_count,const PaStreamCallbackTimeInfo *time_info,PaStreamCallbackFlags status_flags,void *user_data) {
OnlinePaSource *pa_src = reinterpret_cast<OnlinePaSource*>(user_data);
return pa_src->Callback(input,output,frame_count,time_info,status_flags);
}
OnlinePaSource::OnlinePaSource(const uint32 timeout,const uint32 sample_rate,const uint32 rb_size,const uint32 report_interval)
: timeout_(timeout),timed_out_(false),sample_rate_(sample_rate),pa_started_(false),report_interval_(report_interval),nread_calls_(0),noverflows_(0),samples_lost_(0) {
using namespace std;
// Note this will work for 32bit integers but not for 64bit.
// For 64bit integers even double wouldn't work
// You would have to use something like
// int64 rb_bits = 0; while (rb_size != 0) {++rb_bits; rb_size >>= 1;}
// it would be much faster than two logs of FP numbers (even floats),too,// but I don't have the time to test it.
float f = Log(static_cast<float>(rb_size)) / Log(static_cast<float>(2));
int32 rb_bits = static_cast<int32>(ceil(f));
if (rb_bits > 30) // ok,this limit is somewhat arbitrary
throw invalid_argument("PortAudio ring buffer too large!");
rb_size_ = 1 << rb_bits;
ring_buffer_ = new char[rb_size_];
ring_buffer_size_t rbs = PaUtil_InitializeRingBuffer(
&pa_ringbuf_,sizeof(SampleType),rb_size_ / sizeof(SampleType),ring_buffer_);
if (rbs != 0)
KALDI_ERR << "PortAudio ring buffer init error";
PaError paerr = Pa_Initialize();
if (paerr != paNoError)
{
KALDI_ERR << "PortAudio initialization error";
// Monophone,16-bit input hardcoded
KALDI_ASSERT(sizeof(SampleType) == 2 &&
"The current OnlinePaSource code assumes 16-bit input");
}
cout<<"la on va voir si on a des devices"<<endl;
int numDevices;
numDevices=Pa_GetDeviceCount();
cout<< " on a " << numDevices <<endl;
printf( "PortAudio version number = %d\nPortAudio version text = '%s'\n",Pa_GetVersionText() );
paerr = Pa_OpenDefaultStream(&pa_stream_,1,paInt16,sample_rate_,PaCallback,this);
//paerr=Pa_OpenStream
cout<<"Avant la boucle "<<endl;
if (paerr != paNoError)
{
cout<<"On est dans la boucle"<<endl;
const PaDeviceInfo *deviceInfo;
int i=0;
int numDevices;
numDevices=Pa_GetDeviceCount();
cout<<numDevices<<endl;
for (i=0;i<numDevices;i++)
{
deviceInfo=Pa_GetDeviceInfo(i);
cout<<"information sur le device"<<endl;
cout<<"name: "<<deviceInfo->name<<endl;
cout<<"maxInputChannels: "<<deviceInfo->maxInputChannels<<endl;
cout<<"maxOutputChannels: "<<deviceInfo->maxOutputChannels<<endl;
cout<<"defaultSampleRate: "<<deviceInfo->defaultSampleRate<<endl;
}
cout<<Pa_GetErrorText(paerr)<<endl;
KALDI_ERR << "PortAudio Failed to open the default stream";
}
}
OnlinePaSource::~OnlinePaSource() {
if (pa_started_)
Pa_StopStream(pa_stream_);
if (pa_stream_ != 0) {
Pa_CloseStream(pa_stream_);
Pa_Terminate();
}
if (ring_buffer_ != 0)
delete [] ring_buffer_;
}
bool OnlinePaSource::Read(Vector<BaseFloat> *data) {
if (!pa_started_) { // start stream the first time Read() is called
PaError paerr = Pa_StartStream(pa_stream_);
if (paerr != paNoError)
KALDI_ERR << "Error while trying to open PortAudio stream";
pa_started_ = true;
}
Timer timer;
if (report_interval_ != 0
&& (++nread_calls_ % report_interval_) == 0
&& noverflows_ > 0) {
KALDI_VLOG(1) << noverflows_
<< " PortAudio ring buffer overflows detected "
<< "and " << samples_lost_ << " sample(s) were lost";
samples_lost_ = noverflows_ = 0;
}
uint32 nsamples_req = data->Dim(); // samples to request
timed_out_ = false;
while (true) {
ring_buffer_size_t nsamples;
nsamples = PaUtil_GetRingBufferReadAvailable(&pa_ringbuf_);
if (nsamples >= nsamples_req)
break;
if (timeout_ > 0) {
int32 elapsed = static_cast<int32>(timer.Elapsed() * 1000);
if (elapsed > timeout_) {
nsamples_req = nsamples;
timed_out_ = true;
KALDI_VLOG(2) << "OnlinePaSource::Read() timeout";
break;
}
}
Pa_Sleep(2);
}
std::vector<int16> buf(nsamples_req);
rbs_t nsamples_rcv;
nsamples_rcv = PaUtil_ReadRingBuffer(&pa_ringbuf_,buf.data(),nsamples_req);
if (nsamples_rcv != nsamples_req) {
KALDI_WARN << "Requested: " << nsamples_req
<< "; Received: " << nsamples_rcv << " samples";
// This would be a PortAudio error.
}
data->Resize(nsamples_rcv);
for (int i = 0; i < nsamples_rcv; ++i)
(*data)(i) = static_cast<BaseFloat>(buf[i]);
return (nsamples_rcv != 0);
// NOTE (Dan): I'm pretty sure this return value is not right,it Could be
// this way because we're waiting. Vassil or someone will have to figure this
// out.
}
// Accepts the data and writes it to the ring buffer
int OnlinePaSource::Callback(const void *input,ring_buffer_size_t frame_count,PaStreamCallbackFlags status_flags) {
if (report_interval_ != 0) {
if (frame_count > PaUtil_GetRingBufferWriteAvailable(&pa_ringbuf_))
++noverflows_;
}
rbs_t written = PaUtil_WriteRingBuffer(&pa_ringbuf_,input,frame_count);
samples_lost_ += frame_count - written;
return paContinue;
}
#endif // KALDI_NO_PORTAUdio
bool OnlineVectorSource::Read(Vector<BaseFloat> *data) {
KALDI_ASSERT(data->Dim() > 0);
int32 n_elem = std::min(src_.Dim() - pos_,static_cast<uint32>(data->Dim()));
if (n_elem > 0) {
SubVector<BaseFloat> subsrc(src_,pos_,n_elem);
if (data->Dim() == subsrc.Dim()) {
data->copyFromVec(subsrc);
} else {
data->Resize(n_elem);
for (int32 i = 0; i < subsrc.Dim(); ++i)
(*data)(i) = subsrc(i);
}
pos_ += n_elem;
return true;
}
return false;
}
} // namespace kaldi
这个问题的解决方案是什么?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。