📄 ao_dxr2.c
字号:
#include <math.h>#include <stdio.h>#include <stdlib.h>#include <sys/ioctl.h>#include <inttypes.h>#include <dxr2ioctl.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "bswap.h"#include "audio_out.h"#include "audio_out_internal.h"#include "libaf/af_format.h"static ao_info_t info ={ "DXR2 audio output", "dxr2", "Tobias Diedrich <ranma@gmx.at>", ""};LIBAO_EXTERN(dxr2)static int volume=19;extern int dxr2_fd;// to set/get/query special features/parametersstatic int control(int cmd,void *arg){ switch(cmd){ case AOCONTROL_GET_VOLUME: if(dxr2_fd > 0) { ao_control_vol_t* vol = (ao_control_vol_t*)arg; vol->left = vol->right = volume * 19.0 / 100.0; return CONTROL_OK; } return CONTROL_ERROR; case AOCONTROL_SET_VOLUME: if(dxr2_fd > 0) { dxr2_oneArg_t v; float diff; ao_control_vol_t* vol = (ao_control_vol_t*)arg; // We need this trick because the volume stepping is often too small diff = ((vol->left+vol->right) / 2 - (volume*19.0/100.0)) * 19.0 / 100.0; v.arg = volume + (diff > 0 ? ceil(diff) : floor(diff)); if(v.arg > 19) v.arg = 19; if(v.arg < 0) v.arg = 0; if(v.arg != volume) { volume = v.arg; if( ioctl(dxr2_fd,DXR2_IOC_SET_AUDIO_VOLUME,&v) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_DXR2_SetVolFailed,volume); return CONTROL_ERROR; } } return CONTROL_OK; } return CONTROL_ERROR; } return CONTROL_UNKNOWN;}static int freq=0;static int freq_id=0;// open & setup audio device// return: 1=success 0=failstatic int init(int rate,int channels,int format,int flags){ if(dxr2_fd <= 0) return 0; ao_data.outburst=2048; ao_data.samplerate=rate; ao_data.channels=channels; ao_data.buffersize=2048; ao_data.bps=rate*4; ao_data.format=format; freq=rate; switch(rate){ case 48000: freq_id=DXR2_AUDIO_FREQ_48; break; case 96000: freq_id=DXR2_AUDIO_FREQ_96; break; case 44100: freq_id=DXR2_AUDIO_FREQ_441; break; case 32000: freq_id=DXR2_AUDIO_FREQ_32; break; case 22050: freq_id=DXR2_AUDIO_FREQ_2205; break;#ifdef DXR2_AUDIO_FREQ_24 // This is not yet in the dxr2 driver CVS // you can get the patch at // http://www.ranmachan.dyndns.org/~ranma/patches/dxr2.pcm1723.20020513 case 24000: freq_id=DXR2_AUDIO_FREQ_24; break; case 64000: freq_id=DXR2_AUDIO_FREQ_64; break; case 88200: freq_id=DXR2_AUDIO_FREQ_882; break;#endif default: mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_DXR2_UnsupSamplerate,rate); return 0; } return 1;}// close audio devicestatic void uninit(int immed){}// stop playing and empty buffers (for seeking/pause)static void reset(){}// stop playing, keep buffers (for pause)static void audio_pause(){ // for now, just call reset(); reset();}// resume playing, after audio_pause()static void audio_resume(){}extern void dxr2_send_packet(unsigned char* data,int len,int id,int timestamp);extern void dxr2_send_lpcm_packet(unsigned char* data,int len,int id,int timestamp,int freq_id);extern int vo_pts;// return: how many bytes can be played without blockingstatic int get_space(){ float x=(float)(vo_pts-ao_data.pts)/90000.0; int y; if(x<=0) return 0; y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst; if(y>32768) y=32768; return y;}// plays 'len' bytes of 'data'// it should round it down to outburst*n// return: number of bytes playedstatic int play(void* data,int len,int flags){ // MPEG and AC3 don't work :-( if(ao_data.format==AF_FORMAT_MPEG2) dxr2_send_packet(data,len,0xC0,ao_data.pts); else if(ao_data.format==AF_FORMAT_AC3) dxr2_send_packet(data,len,0x80,ao_data.pts); else { int i; //unsigned short *s=data; uint16_t *s=data;#ifndef WORDS_BIGENDIAN for(i=0;i<len/2;i++) s[i] = bswap_16(s[i]);#endif dxr2_send_lpcm_packet(data,len,0xA0,ao_data.pts-10000,freq_id); } return len;}// return: delay in seconds between first and last sample in bufferstatic float get_delay(){ return 0.0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -