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

📄 pa_linux_asihpi.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com *  * PortAudio v18 version of AudioScience HPI driver by Fred Gleason <fredg@salemradiolabs.com> * PortAudio v19 version of AudioScience HPI driver by Ludwig Schwardt <schwardt@sun.ac.za> *  * Copyright (c) 2003 Fred Gleason * Copyright (c) 2005,2006 Ludwig Schwardt * * 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. *//* * Modification History * 12/2003 - Initial version * 09/2005 - v19 version [rewrite] *//** @file @ingroup hostapi_src @brief Host API implementation supporting AudioScience cards         via the Linux HPI interface.  <h3>Overview</h3>  This is a PortAudio implementation for the AudioScience HPI Audio API on the Linux platform. AudioScience makes a range of audio adapters customised for the broadcasting industry, with support for both Windows and Linux. More information on their products can be found on their website:      http://www.audioscience.com  Documentation for the HPI API can be found at:      http://www.audioscience.com/internet/download/sdk/spchpi.pdf  The Linux HPI driver itself (a kernel module + library) can be downloaded from:      http://www.audioscience.com/internet/download/linux_drivers.htm  <h3>Implementation strategy</h3>  *Note* Ideally, AudioScience cards should be handled by the PortAudio ALSA  implementation on Linux, as ALSA is the preferred Linux soundcard API. The existence of this host API implementation might therefore seem a bit flawed. Unfortunately, at  the time of the creation of this implementation (June 2006), the PA ALSA implementation  could not make use of the existing AudioScience ALSA driver. PA ALSA uses the  "memory-mapped" (mmap) ALSA access mode to interact with the ALSA library, while the  AudioScience ALSA driver only supports the "read-write" access mode. The appropriate solution to this problem is to add "read-write" support to PortAudio ALSA, thereby extending the range of soundcards it supports (AudioScience cards are not the only ones with this problem). Given the author's limited knowledge of ALSA and the  simplicity of the HPI API, the second-best solution was born...  The following mapping between HPI and PA was followed: HPI subsystem => PortAudio host API HPI adapter => nothing specific HPI stream => PortAudio device  Each HPI stream is either input or output (not both), and can support different channel counts, sampling rates and sample formats. It is therefore a more natural fit to a PA device. A PA stream can therefore combine two HPI streams (one input and one output) into a "full-duplex" stream. These HPI streams can even be on different physical adapters. The two streams ought to be sample-synchronised when they reside on the same adapter, as most AudioScience adapters derive their ADC and DAC clocks from one master clock. When combining two adapters into one full-duplex stream, however, the use of a word clock connection between the  adapters is strongly recommended.   The HPI interface is inherently blocking, making use of read and write calls to transfer data between user buffers and driver buffers. The callback interface therefore requires a helper thread ("callback engine") which periodically transfers data (one thread per PA stream, in fact). The current implementation explicitly sleeps via Pa_Sleep() until  enough samples can be transferred (select() or poll() would be better, but currently seems  impossible...). The thread implementation makes use of the Unix thread helper functions and some pthread calls here and there. If a unified PA thread exists, this host API  implementation might also compile on Windows, as this is the only real Linux-specific  part of the code.  There is no inherent fixed buffer size in the HPI interface, as in some other host APIs. The PortAudio implementation contains a buffer that is allocated during OpenStream and used to transfer data between the callback and the HPI driver buffer. The size of this buffer is quite flexible and is derived from latency suggestions and matched to the requested callback buffer size as far as possible. It can become quite huge, as the AudioScience cards are typically geared towards higher-latency applications and contain large hardware buffers.  The HPI interface natively supports most common sample formats and sample rates (some conversion is done on the adapter itself).  Stream time is measured based on the number of processed frames, which is adjusted by the number of frames currently buffered by the HPI driver.  There is basic support for detecting overflow and underflow. The HPI interface does not explicitly indicate this, so thresholds on buffer levels are used in combination with stream state. Recovery from overflow and underflow is left to the PA client.  Blocking streams are also implemented. It makes use of the same polling routines that the callback interface uses, in order to prevent the allocation of variable-sized buffers during reading and writing. The framesPerBuffer parameter is therefore still  relevant, and this can be increased in the blocking case to improve efficiency.  The implementation contains extensive reporting macros (slightly modified PA_ENSURE and PA_UNLESS versions) and a useful stream dump routine to provide debugging feedback.  Output buffer priming via the user callback (i.e. paPrimeOutputBuffersUsingStreamCallback and friends) is not implemented yet. All output is primed with silence.  Please send bug reports etc. to Ludwig Schwardt <schwardt@sun.ac.za> */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>          /* strlen() */#include <pthread.h>         /* pthreads and friends */#include <assert.h>          /* assert */#include <math.h>            /* ceil, floor */#include <asihpi/hpi.h>      /* HPI API */#include "portaudio.h"       /* PortAudio API */#include "pa_util.h"         /* PA_DEBUG, other small utilities */#include "pa_unix_util.h"    /* Unix threading utilities */#include "pa_allocation.h"   /* Group memory allocation */#include "pa_hostapi.h"      /* Host API structs */#include "pa_stream.h"       /* Stream interface structs */#include "pa_cpuload.h"      /* CPU load measurer */#include "pa_process.h"      /* Buffer processor */#include "pa_converters.h"   /* PaUtilZeroer *//* -------------------------------------------------------------------------- *//* * Defines *//* Error reporting and assertions *//** Evaluate expression, and return on any PortAudio errors */#define PA_ENSURE_(expr) \    do { \        PaError paError = (expr); \        if( UNLIKELY( paError < paNoError ) ) \        { \            PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \            result = paError; \            goto error; \        } \    } while (0);/** Assert expression, else return the provided PaError */#define PA_UNLESS_(expr, paError) \    do { \        if( UNLIKELY( (expr) == 0 ) ) \        { \            PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \            result = (paError); \            goto error; \        } \    } while( 0 );/** Check return value of HPI function, and map it to PaError */#define PA_ASIHPI_UNLESS_(expr, paError) \    do { \        HW16 hpiError = (expr); \        /* If HPI error occurred */ \        if( UNLIKELY( hpiError ) ) \        { \	    char szError[256]; \	    HPI_GetErrorText( hpiError, szError ); \	    PA_DEBUG(( "HPI error %d occurred: %s\n", hpiError, szError )); \	    /* This message will always be displayed, even if debug info is disabled */ \            PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \            if( (paError) == paUnanticipatedHostError ) \	    { \	        PA_DEBUG(( "Host error description: %s\n", szError )); \	        /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \	        if( pthread_equal( pthread_self(), paUnixMainThread ) ) \                { \		    PaUtil_SetLastHostErrorInfo( paInDevelopment, hpiError, szError ); \                } \	    } \	    /* If paNoError is specified, continue as usual */ \            /* (useful if you only want to print out the debug messages above) */ \	    if( (paError) < 0 ) \	    { \	        result = (paError); \	        goto error; \	    } \        } \    } while( 0 );/** Report HPI error code and text */#define PA_ASIHPI_REPORT_ERROR_(hpiErrorCode) \    do { \        char szError[256]; \        HPI_GetErrorText( hpiError, szError ); \        PA_DEBUG(( "HPI error %d occurred: %s\n", hpiError, szError )); \        /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \        if( pthread_equal( pthread_self(), paUnixMainThread ) ) \	{ \	    PaUtil_SetLastHostErrorInfo( paInDevelopment, (hpiErrorCode), szError ); \	} \    } while( 0 );/* Defaults *//** Sample formats available natively on AudioScience hardware */#define PA_ASIHPI_AVAILABLE_FORMATS_ (paFloat32 | paInt32 | paInt24 | paInt16 | paUInt8)/** Enable background bus mastering (BBM) for buffer transfers, if available (see HPI docs) */#define PA_ASIHPI_USE_BBM_ 1/** Minimum number of frames in HPI buffer (for either data or available space). If buffer contains less data/space, it indicates xrun or completion. */#define PA_ASIHPI_MIN_FRAMES_ 1152/** Minimum polling interval in milliseconds, which determines minimum host buffer size */#define PA_ASIHPI_MIN_POLLING_INTERVAL_ 10/* -------------------------------------------------------------------------- *//* * Structures *//** Host API global data */typedef struct PaAsiHpiHostApiRepresentation{    /* PortAudio "base class" - keep the baseRep first! (C-style inheritance) */    PaUtilHostApiRepresentation baseHostApiRep;    PaUtilStreamInterface callbackStreamInterface;    PaUtilStreamInterface blockingStreamInterface;    PaUtilAllocationGroup *allocations;    /* implementation specific data goes here */    PaHostApiIndex hostApiIndex;    /** HPI subsystem pointer */    HPI_HSUBSYS *subSys;}PaAsiHpiHostApiRepresentation;/** Device data */typedef struct PaAsiHpiDeviceInfo{    /* PortAudio "base class" - keep the baseRep first! (C-style inheritance) */    /** Common PortAudio device information */    PaDeviceInfo baseDeviceInfo;    /* implementation specific data goes here */    /** HPI subsystem (required for most HPI calls) */    HPI_HSUBSYS *subSys;    /** Adapter index */    HW16 adapterIndex;    /** Adapter model number (hex) */    HW16 adapterType;    /** Adapter HW/SW version */    HW16 adapterVersion;    /** Adapter serial number */    HW32 adapterSerialNumber;    /** Stream number */    HW16 streamIndex;    /** 0=Input, 1=Output (HPI streams are either input or output but not both) */    HW16 streamIsOutput;}PaAsiHpiDeviceInfo;/** Stream state as defined by PortAudio. It seems that the host API implementation has to keep track of the PortAudio stream state. Please note that this is NOT the same as the state of the underlying HPI stream. By separating these two concepts, a lot of flexibility is gained. There is a rough match between the two, of course, but forcing a precise match is difficult. For example, HPI_STATE_DRAINED can occur during the Active state of PortAudio (due to underruns) and also during CallBackFinished in the case of an output stream. Similarly, HPI_STATE_STOPPED mostly coincides with the Stopped PortAudio state, by may also occur in the CallbackFinished state when recording is finished.  Here is a rough match-up:  PortAudio state   =>     HPI state ---------------          --------- Active            =>     HPI_STATE_RECORDING, HPI_STATE_PLAYING, (HPI_STATE_DRAINED) Stopped           =>     HPI_STATE_STOPPED

⌨️ 快捷键说明

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