📄 audriv_al.c
字号:
/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp> Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <errno.h>#include <unistd.h>#include <dmedia/audio.h>#include "timidity.h"#include "aenc.h"#include "audriv.h"#include "audio_cnv.h"#include "timer.h"#if !defined(SGI_OLDAL) && !defined(SGI_NEWAL)#if defined(sgi) && __mips - 0 == 1#define SGI_OLDAL#endif#endif /* SGI_OLDAL */#ifdef SGI_OLDAL#define alSetWidth ALsetwidth#define alNewConfig ALnewconfig#define alFreeConfig ALfreeconfig#define alSetSampFmt ALsetsampfmt#define alClosePort ALcloseport#define alSetChannels ALsetchannels#define alOpenPort ALopenport#define alGetFrameTime ALgetframetime#define alSetQueueSize ALsetqueuesize#define alGetFilled ALgetfilled#define alSetConfig ALsetconfig#define alGetFillable ALgetfillable#define alWriteFrames(p, s, n) ALwritesamps(p, s, (n) * play_nchannels)#define stamp_t unsigned long long#endif /* SGI_OLDAL */#define OUT_AUDIO_QUEUE_SIZE 200000void (* audriv_error_handler)(const char *errmsg) = NULL;static ALconfig out_config;static ALport out = NULL;static Bool audio_write_noblocking = False;static int play_nchannels = 1;static int play_frame_width = 2;static int play_encoding = AENC_SIGWORDB;static int play_sample_rate = 8000;static long reset_samples, play_counter;static double play_start_time;#ifndef SGI_OLDALstatic ALparamInfo out_ginfo;#endifchar audriv_errmsg[BUFSIZ];#ifndef SGI_OLDAL#define ALERROR alGetErrorString(oserror())#else#define ALERROR strerror(oserror())#endif /* SGI_OLDAL */static void audriv_err(const char *msg){ strncpy(audriv_errmsg, msg, sizeof(audriv_errmsg)); if(audriv_error_handler != NULL) audriv_error_handler(audriv_errmsg);}static int audriv_al_set_width(ALconfig c, int encoding){ if(encoding == AENC_G711_ULAW) return alSetWidth(c, 2); else return alSetWidth(c, AENC_SAMPW(encoding));}Bool audriv_setup_audio(void)/* オ〖ディオの介袋步を乖いますˉ * 喇根した眷圭は True を·己窃した眷圭は False を手しますˉ */{ if(out_config) return True; if((out_config = alNewConfig()) == NULL) { audriv_err(ALERROR); return False; } out = NULL;#ifndef SGI_OLDAL if(alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &out_ginfo) < 0) { audriv_err(ALERROR); alFreeConfig(out_config); out_config = NULL; return False; }#endif /* SGI_OLDAL */ if(alSetSampFmt(out_config, AL_SAMPFMT_TWOSCOMP) < 0) { audriv_err(ALERROR); return False; }#if 0 if(alSetQueueSize(out_config, OUT_AUDIO_QUEUE_SIZE) != 0) { fprintf(stderr, "Warning: Can't set queue size: %d\n", OUT_AUDIO_QUEUE_SIZE); }#else alSetQueueSize(out_config, OUT_AUDIO_QUEUE_SIZE);#endif return True;}void audriv_free_audio(void)/* audio の稿借妄を乖いますˉ */{ if(!out_config) return; if(out != NULL) { alClosePort(out); out = NULL; } alFreeConfig(out_config); out_config = NULL; if(out_config != NULL) alFreeConfig(out_config); out_config = NULL;}#ifndef SGI_OLDALstatic Bool audriv_al_set_rate(ALport port, unsigned long rate){ ALpv pv; int r; r = alGetResource(port); pv.param = AL_RATE; pv.value.ll = alIntToFixed(rate); if(alSetParams(r, &pv, 1) < 0) return False; return True;}#elsestatic Bool audriv_al_set_rate(ALport port, unsigned long rate){ long pv[2]; pv[0] = (port == out ? AL_OUTPUT_RATE : AL_INPUT_RATE); pv[1] = rate; if(ALsetparams(AL_DEFAULT_DEVICE, pv, 2) < 0) return False; return True;}#endif /* SGI_OLDAL */Bool audriv_play_open(void)/* audio を遍琳脱に倡き·いつでも audriv_write() により遍琳材墙な * 觉轮にしますˉ贷に倡いている眷圭はなにも乖いませんˉ * 喇根した眷圭は True を·己窃した眷圭は False を手しますˉ */{ if(out) return True; if(audriv_al_set_width(out_config, play_encoding) < 0) { audriv_err(ALERROR); return False; } alSetChannels(out_config, play_nchannels); out = alOpenPort("audriv", "w", out_config); if(!out) { audriv_err(ALERROR); return False; } if(audriv_al_set_rate(out, play_sample_rate) == False) { audriv_err(ALERROR); alClosePort(out); out = NULL; return False; } alSetConfig(out, out_config); reset_samples = 0; play_counter = 0; return True;}void audriv_play_close(void)/* 遍琳脱にオ〖プンされた audio を誓じますˉすでに誓じている * 眷圭はなにも乖いませんˉ */{ if(!out) return; while(audriv_play_active() == 1) audriv_wait_play(); alClosePort(out); out = NULL;}long audriv_play_stop(void)/* 遍琳を篓郝に匿贿し·匿贿木涟のサンプル眶を手しますˉ * audriv_play_stop() の钙び叫しによって·audio は誓じますˉ * audio が贷に誓じている眷圭に audriv_play_stop() を钙び叫した眷圭は 0 を * 手しますˉ * エラ〖の眷圭は -1 を手しますˉ */{ long samp; if(!out) return 0; samp = audriv_play_samples(); alClosePort(out); reset_samples = play_counter = 0; out = NULL; return samp;}Bool audriv_is_play_open(void)/* audio が遍琳でオ〖プンされている眷圭は True, * 誓じている眷圭は False を手しますˉ */{ return out != NULL;}Bool audriv_set_play_volume(int volume)/* 遍琳不翁を 0 × 255 の认跋柒で肋年しますˉ0 は痰不·255 は呵络不翁ˉ * 0 踏塔は 0·255 を亩える猛は 255 に霹擦ˉ * 喇根した眷圭は True を·己窃した眷圭は False を手しますˉ */{#ifndef SGI_OLDAL double gain; ALfixed lrgain[2]; ALpv pv; int resource; if(volume < 0) volume = 0; else if(volume > 255) volume = 255; if(volume == 0) { if(out_ginfo.specialVals & AL_NEG_INFINITY_BIT) gain = alFixedToDouble(AL_NEG_INFINITY); else gain = alFixedToDouble(out_ginfo.min.ll); } else if(volume == 255) { gain = alFixedToDouble(out_ginfo.max.ll); } else { double min, max; min = alFixedToDouble(out_ginfo.min.ll); max = alFixedToDouble(out_ginfo.max.ll); gain = min + (max - min) * (volume - 1) * (1.0/255); if(gain < min) gain = min; else if(gain > max) gain = max; } if(out == NULL) resource = AL_DEFAULT_OUTPUT; else resource = alGetResource(out); lrgain[0] = lrgain[1] = alDoubleToFixed(gain); pv.param = AL_GAIN; pv.value.ptr = lrgain; pv.sizeIn = 2; if(alSetParams(resource, &pv, 1) < 0) { audriv_err(ALERROR); return False; } return True;#else long gain[4]; if(volume < 0) volume = 0; else if(volume > 255) volume = 255; gain[0] = AL_LEFT_SPEAKER_GAIN; gain[1] = volume; gain[2] = AL_RIGHT_SPEAKER_GAIN; gain[3] = volume; if(ALsetparams(AL_DEFAULT_DEVICE, gain, 4) < 0) { audriv_err(ALERROR); return False; } return True;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -