青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

zyzx的小窩

C/C++,GUI,個人移動存儲,zyzx_lsl@163.com

 

簡單音頻播放:音頻播放核心實現

tag:C,音頻播放,libsndfile,PortAudio

/* Create by zyzx
* Created 2008-08-09
* Modified 2008-08-09
*/

一、準備
?????? 1、依賴庫PortAudio(http://www.portaudio.com/
???????????? Win32平臺編譯見《Win32環境PortAudio庫編譯簡介:音頻播放

?????? 2、依賴庫libsndfile (http://www.mega-nerd.com/libsndfile/
???????????? 簡介:是一個開源跨平臺C庫,用于解碼一系列的音頻文件格式如WAV,AIFF,SF等等。初期支持Mp3格式的,后來由于種種原因取消了對Mp3格式的支持。
???????????? 編譯環境:MinGW+MSYSMinGW+MSYS的C\C++編程環境安裝與升級
???????????? 1)從libsndfile上下載libsndfile-1.0.17.tar.gz(當前最高版本)
???????????? 2)將libsndfile-1.0.17.tar.gz復制到MinGW/Msys安裝目錄Msys/home目錄下
???????????? 3)打開Msys模擬環境
?????????????????? $ cd /home
?????????????????? $ tar jxf libsndfile-1.0.17.tar.gz && cd libsndfile-1.0.17
?????????????????? $ ./configure
?????????????????? $ make && make install
???????????? 4)如果懶點,直接使用源碼包中發布的libsndfile-1.dll和sndfile.h文件得了。

二、編碼試驗
??????? 嘿,,經過層層碰壁后,,小弟終于初窺了點門道,,成功的摸索出了一條小道。。不過不要緊,萬事開頭難,,接下來嗎。。距離自己的音頻播放器又近了一步。。

??????? 值得注意的地方:
??????? 如下源碼參照 PortAudio庫中示例patest_read_write_wire.c 和 libsndfile 庫中示例sndfile-play.c 文件進行的修改。。所以還有很多地方懶得去理會,代碼難看點。。
??????? 1)其中 while(1) { ......} 語句,可以提取到一個線程中去。此線程專門負責給聲卡喂數據,使用雙緩存或三緩存,當某個緩存塊數據全部喂到聲卡后,通知數據讀取線程開工了。
??????? 2)為了節省空間咱不能一下申請WIN32_AUDIO_BUFF_LEN這大的內存區域,使用多線程來解決。添加數據讀取線程。。
??????? 3)為了可以播放,暫停,... 咱得提供一個GUI界面,所以就涉及到線程通訊了哦。。
??????? 4)為了保證跨平臺性,還得去找個跨平臺的線程庫啊。。Boost庫中包含線程相關的,就先學習ing...


下面是源碼:(還要在vs里設置庫環境)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portaudio.h"

#include "windows.h"
#include "sndfile.h"

#define SF_DLL??? ??? "libsndfile-1.dll"

typedef int??? ??? ?? ?????? (*P_sf_command)(SNDFILE *sndfile, int command, void *data, int datasize);
typedef SNDFILE*??? (*P_sf_open)(const char *path, int mode, SF_INFO *sfinfo);
typedef sf_count_t???? (*P_sf_read_short)(SNDFILE *sndfile, short *ptr, sf_count_t items);
typedef int??? ??? ??????? ?? (*P_sf_close)(SNDFILE *sndfile);
typedef int??? ??? ????????? (*P_sf_perror)(SNDFILE *sndfile);
typedef const char*?? (*P_sf_strerror)(SNDFILE *sndfile);
typedef sf_count_t??? (*P_sf_read_float)(SNDFILE *sndfile, float *ptr, sf_count_t items);
typedef sf_count_t??? (*P_sf_read_int)(SNDFILE *sndfile, int *ptr, sf_count_t items);

#define sf_command( hInstan, p )??? ??? P_sf_command p = (P_sf_command)GetProcAddress( hInstan, "sf_command")
#define sf_open( hInstan, p )??? ??? ??? P_sf_open p = (P_sf_open)GetProcAddress( hInstan, "sf_open" )
#define sf_close( hInstan, p )??? ??? ??? P_sf_close p = (P_sf_close)GetProcAddress( hInstan, "sf_close" )
#define sf_perror( hInstan, p )??? ??? ??? P_sf_perror p = (P_sf_perror)GetProcAddress( hInstan, "sf_perror" )
#define sf_read_short( hInstan, p )??? ??? P_sf_read_short p = (P_sf_read_short)GetProcAddress( hInstan, "sf_read_short" )
#define sf_read_int( hInstan, p )??? ??? P_sf_read_int p = (P_sf_read_int)GetProcAddress( hInstan, "sf_read_int" )
#define sf_read_float( hInstan, p )??? ??? P_sf_read_float p = (P_sf_read_float)GetProcAddress( hInstan, "sf_read_float" )
#define sf_strerror( hInstan, p )??? ??? P_sf_strerror p = (P_sf_strerror)GetProcAddress( hInstan, "sf_strerror" )

//* - 整上面這些也是沒辦法啊,在VS里只有*.dll和頭文件,咱只有動態加載了。

//* - 保存動態庫句柄
HINSTANCE?? ghIns;??

/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
#define SAMPLE_RATE (44100)?????????????????????????????????????? //* - 采樣率
#define FRAMES_PER_BUFFER ( 64 * 1024 )???????????????? //* - 緩存大小 - 向聲卡驅動寫數據時候的
#define NUM_CHANNELS??? (2)?????????????????????????????????????????? //* - 聲道數
/* #define DITHER_FLAG???? (paDitherOff) */
#define DITHER_FLAG???? (0) /**/

/* Select sample format. */

#define PA_SAMPLE_TYPE paFloat32???????????????????????????? //* - 采樣點占用大小32位的float型
#define SAMPLE_SIZE (4)?????????????????????????????????????????????????? //* - 采樣點占用4字節
#define SAMPLE_SILENCE (0.0f)
#define CLEAR(a) bzero( (a), FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%.8f"

#define WIN32_AUDIO_BUFF_LEN??? 32 * 1024 * 1024 //* - 音頻數據(解碼后)緩沖區域大小

typedef struct
{
??? float*??? ??? buffer;????????????????????? //* - 音頻數據(解碼后)緩沖區域

??? long??? ??? current, bufferlen ;??? //* - 當前播放到達的數據點,實際全部音頻數據長度

??? SNDFILE ??? *sndfile ;???????????? //* - libsndfile 庫 基本 結構 -- 類似句柄或結構體指針
??? SF_INFO ??? sfinfo ;??????????????? //* - libsndfile 庫 讀取的音頻基本信息(如采樣率,聲道,等等)

??? sf_count_t??? remaining ;???????? //* - 好像沒用到
} Win32_Audio_Data ;


/*******************************************************************/
int main(int argc, char *argv [] );
int main(int argc, char *argv [] )
{
??? HINSTANCE?? hIns;
??? hIns = LoadLibrary( SF_DLL );????????? //* 加載 libsndfile-1.dll

??? Win32_Audio_Data audio_data;

??? audio_data.buffer = new float[ WIN32_AUDIO_BUFF_LEN ] ;
??? audio_data.current = 0;

??? ghIns = hIns;

??? PaStreamParameters inputParameters, outputParameters;
??? PaStream *stream = NULL;
??? PaError err;
??? int i;
??? int numBytes;


??? printf("patest_read_write_wire.c\n"); fflush(stdout);

??? err = Pa_Initialize();
??? if( err != paNoError ) goto error;

??? //* - 打開****.***音頻文件
??? sf_open( ghIns, Open );
??? if (! (audio_data.sndfile = Open (argv[1], SFM_READ, &(audio_data.sfinfo))))
??? {???
??? ??? sf_strerror( ghIns, Strerror );
??? ??? puts ( Strerror(NULL) ) ;

??? ??? goto error;
??? }

??? //* 以float格式讀取并解析音頻格式 長度標為WIN32_AUDIO_BUFF_LEN,基本上能全部讀取文件
??? sf_read_float( ghIns, ReadFloat );
??? audio_data.bufferlen += (long) ReadFloat (audio_data.sndfile, (float*)(audio_data.buffer ), WIN32_AUDIO_BUFF_LEN/*audio_data.sfinfo.frames */) ;


??? printf( "-------------------------------\n" );

??? printf( "Output samplerate %d\n", audio_data.sfinfo.samplerate );
??? printf( "Output frames %d\n", audio_data.sfinfo.frames );
??? printf( "Output channels %d\n", audio_data.sfinfo.channels );
??? printf( "seekable %d\n ", audio_data.sfinfo.seekable );
??? printf( "format is %d\n ", audio_data.sfinfo.format );
??? printf( "Sections is %d\n ", audio_data.sfinfo.sections );

??? printf( "Read buffer len %d\n" , audio_data.bufferlen );

??? printf( "-------------------------------\n" );

??? //inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
??? //printf( "Input device # %d.\n", inputParameters.device );
??? //printf( "Input LL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency );
??? //printf( "Input HL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency );
??? //inputParameters.channelCount = audio_data.sfinfo.channels;//NUM_CHANNELS;
??? //inputParameters.sampleFormat = PA_SAMPLE_TYPE;
??? //inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ;
??? //inputParameters.hostApiSpecificStreamInfo = NULL;

??? outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
??? printf( "Output device # %d.\n", outputParameters.device );
??? printf( "Output LL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency );
??? printf( "Output HL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency );
??? outputParameters.channelCount = audio_data.sfinfo.channels;//NUM_CHANNELS;
??? outputParameters.sampleFormat = PA_SAMPLE_TYPE;
??? outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
??? outputParameters.hostApiSpecificStreamInfo = NULL;

??? /* -- setup -- */

??? err = Pa_OpenStream(
??? ??? &stream,
??? ??? NULL,//&inputParameters,???????????????????????????????????????? //* - 麥克風
??? ??? &outputParameters,?????????????????????????????????????????????????? //* - 揚聲器
??? ??? audio_data.sfinfo.samplerate,//SAMPLE_RATE,?? //* - 采樣率
??? ??? FRAMES_PER_BUFFER,??????????????????????????????????????? //* - 緩沖區
??? ??? paClipOff,????? /* we won't output out of range samples so don't bother clipping them */
??? ??? NULL, /* no callback, use blocking API */
??? ??? NULL ); /* no callback, so no callback userData */
??? if( err != paNoError ) goto error;

??? //err = Pa_StartStream( stream );
??? //if( err != paNoError ) goto error;
??? //printf("Wire on. Will run one minute.\n"); fflush(stdout);

??? //for( i=0; i<(60*SAMPLE_RATE)/FRAMES_PER_BUFFER; ++i )
??? //{
??? //??? err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
??? //??? if( err ) goto xrun;
??? //??? err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
??? //??? if( err ) goto xrun;
??? //}
??? //err = Pa_StopStream( stream );
??? //if( err != paNoError ) goto error;

??? //CLEAR( sampleBlock );

??? err = Pa_StartStream( stream );
??? if( err != paNoError ) goto error;
??? printf("Wire on. Interrupt to stop.\n"); fflush(stdout);

??? while( 1 )
??? {
??????? //* - 此函數為同步函數,它一直等待到buffer中的數據全部寫入聲卡驅動才返回
??????? //* - 緩沖去長度為FRAMES_PER_BUFFER,指的是一個聲道上的數據大小
??? ??? err = Pa_WriteStream( stream, audio_data.buffer + audio_data.current/*sampleBlock*/, FRAMES_PER_BUFFER );
??? ??? audio_data.current = audio_data.current + FRAMES_PER_BUFFER * NUM_CHANNELS ;

??? ??? //if( audio_data.current + FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE > audio_data.bufferlen ) break;

??? ??? printf( "%d\n", audio_data.current);

??? ??? if( err ) goto xrun;
??? ??? //err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
??? ??? //if( err ) goto xrun;
??? }
??? err = Pa_StopStream( stream );
??? if( err != paNoError ) goto error;

??? Pa_CloseStream( stream );

??? free( sampleBlock );

??? Pa_Terminate();
??? return 0;

xrun:
??? if( stream ) {
??? ??? Pa_AbortStream( stream );
??? ??? Pa_CloseStream( stream );
??? }
??? free( sampleBlock );
??? Pa_Terminate();
??? if( err & paInputOverflow )
??? ??? fprintf( stderr, "Input Overflow.\n" );
??? if( err & paOutputUnderflow )
??? ??? fprintf( stderr, "Output Underflow.\n" );

??? delete [] audio_data.buffer;
??? FreeLibrary( ghIns );
??? return -2;

error:
??? if( stream ) {
??? ??? Pa_AbortStream( stream );
??? ??? Pa_CloseStream( stream );
??? ??? FreeLibrary( ghIns );
??? }
??? free( sampleBlock );
??? 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 ) );

??? delete [] audio_data.buffer;
??? FreeLibrary( ghIns );
??? return -1;
}

三、某次播放Wav文件 截圖 -- 紀念

TestPortAudio.png

posted on 2009-04-27 17:17 zyzx 閱讀(2385) 評論(0)  編輯 收藏 引用 所屬分類: OpenSource開源

導航

統計

常用鏈接

留言簿(1)

隨筆分類

隨筆檔案

常用鏈接

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲性av在线| 亚洲国产成人91精品| 黄色成人在线网站| 韩国三级在线一区| 一区在线电影| 亚洲精品午夜精品| 亚洲亚洲精品三区日韩精品在线视频| 一区二区欧美激情| 欧美一区二区三区视频免费| 久久久久**毛片大全| 欧美福利视频| 一区二区精品| 久久性色av| 欧美性天天影院| 一区二区三区在线高清| 日韩亚洲欧美一区二区三区| 亚洲女人天堂av| 老司机凹凸av亚洲导航| 亚洲黄色高清| 欧美一区观看| 欧美日韩大片一区二区三区| 国产日韩专区| 亚洲午夜影视影院在线观看| 久久久久久久性| 99在线观看免费视频精品观看| 性欧美超级视频| 欧美日韩精品中文字幕| 国产在线高清精品| 亚洲婷婷在线| 欧美激情久久久久久| 亚洲女与黑人做爰| 欧美精品七区| 亚洲福利专区| 久久精品国产亚洲一区二区三区| 亚洲激情在线播放| 久久精品综合网| 国产精品一区二区在线观看不卡| 亚洲人人精品| 久久久www成人免费精品| 亚洲欧美日韩在线一区| 欧美88av| 在线观看福利一区| 欧美在线综合视频| 一本色道久久88精品综合| 浪潮色综合久久天堂| 国产日韩1区| 亚洲婷婷综合色高清在线| 亚洲精品乱码久久久久| 久久久久国产一区二区三区四区| 国产精品一区在线播放| 亚洲一二三区精品| 亚洲精品国产精品乱码不99按摩| 久久久五月婷婷| 国产日韩亚洲欧美| 欧美在线免费观看亚洲| 亚洲综合久久久久| 国产精品区免费视频| 亚洲欧美日本精品| 一本一本久久a久久精品牛牛影视| 鲁大师成人一区二区三区 | 麻豆精品国产91久久久久久| 国产一区二区精品| 久久久久久久性| 久久久久久久一区二区| 极品裸体白嫩激情啪啪国产精品| 欧美中文在线观看| 久久精品91久久香蕉加勒比| 怡红院av一区二区三区| 欧美激情欧美激情在线五月| 欧美精品福利| 亚洲永久免费av| 午夜精品久久久久久久蜜桃app | 亚洲欧美一区二区在线观看| 国产欧美日韩综合| 久久久久久亚洲精品杨幂换脸| 久久国内精品视频| 亚洲高清二区| 亚洲区中文字幕| 欧美性色视频在线| 久久在线播放| 欧美日韩高清在线播放| 亚洲欧美日韩国产另类专区| 午夜欧美大尺度福利影院在线看| 国内精品久久久久久| 欧美电影免费观看高清| 欧美日韩一区在线视频| 欧美一区亚洲二区| 玖玖精品视频| 亚洲欧美成人一区二区三区| 久久se精品一区二区| 亚洲精品中文字| 亚洲欧美激情四射在线日| 亚洲茄子视频| 欧美福利网址| 亚洲欧美www| 久久免费午夜影院| 亚洲在线一区| 免费观看成人| 性欧美大战久久久久久久久| 久久亚洲私人国产精品va| 亚洲一区二区免费在线| 久久嫩草精品久久久精品| 亚洲一区三区电影在线观看| 久久久久久久网站| 欧美一乱一性一交一视频| 欧美成人免费视频| 久久九九热re6这里有精品| 欧美人与性禽动交情品| 裸体女人亚洲精品一区| 国产精品久久毛片a| 亚洲福利在线看| 伊人久久大香线| 西瓜成人精品人成网站| 亚洲影院免费观看| 欧美国产精品va在线观看| 久久免费视频一区| 国产精品青草久久久久福利99| 亚洲人成毛片在线播放| 亚洲国产精品一区二区第一页| 欧美与黑人午夜性猛交久久久| 亚洲综合精品一区二区| 欧美日本高清视频| 亚洲高清在线播放| 亚洲国产成人av在线| 久久精品论坛| 久久精品视频播放| 国产日韩精品一区二区三区在线| 亚洲精品资源| 亚洲精品人人| 欧美粗暴jizz性欧美20| 欧美成人高清视频| 亚洲国产三级在线| 久久永久免费| 亚洲成人在线网站| 久久久久久亚洲综合影院红桃 | 一区二区三区四区五区精品| 美女在线一区二区| 亚洲第一页在线| 亚洲精品在线观看视频| 欧美激情精品久久久六区热门| 欧美激情一区三区| 亚洲九九九在线观看| 欧美激情精品久久久久久| 91久久久亚洲精品| 一区二区欧美在线| 国产精品成人观看视频国产奇米| 国产精品99久久久久久www| 午夜伦理片一区| 精品51国产黑色丝袜高跟鞋| 免费久久精品视频| 亚洲毛片一区二区| 欧美一级淫片aaaaaaa视频| 国产午夜精品美女视频明星a级| 欧美在线免费视频| 亚洲高清视频在线观看| 亚洲一区三区视频在线观看| 国产精品系列在线| 欧美日韩免费高清| 亚洲欧美日韩精品久久久| 国产精品盗摄久久久| 午夜精品久久久久| 久热re这里精品视频在线6| 亚洲国产精品视频一区| 欧美日韩视频不卡| 亚洲女女做受ⅹxx高潮| 久久久视频精品| 亚洲精品在线视频观看| 国产精品swag| 猫咪成人在线观看| 亚洲中午字幕| 亚洲成色www8888| 亚洲男人第一网站| 亚洲国产成人av| 国产乱码精品一区二区三区不卡 | 亚洲视屏一区| 国产一区美女| 欧美午夜一区| 另类欧美日韩国产在线| 亚洲天堂久久| 亚洲电影免费观看高清完整版| 在线亚洲伦理| 亚洲国产精品va在看黑人| 国产精品高清在线观看| 久久久午夜电影| 亚洲欧美日韩成人高清在线一区| 麻豆成人小视频| 欧美影院久久久| 亚洲一区二区三区四区在线观看 | 免费久久99精品国产自| 亚洲欧美另类久久久精品2019| 在线精品国产成人综合| 国产精品色午夜在线观看| 欧美精品国产| 麻豆成人在线| 久久激情中文| 欧美一区在线视频| 一区二区三区视频在线| 亚洲精品日日夜夜| 亚洲国内自拍| 亚洲国产欧美一区二区三区久久 |