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

📄 audio.c

📁 linux下的任天堂模拟器代码。供大家参考。
💻 C
字号:
/*Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )http://www.zsnes.comhttp://sourceforge.net/projects/zsneshttps://zsnes.bountysource.comThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseversion 2 as published by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "../gblhdr.h"#include <stdbool.h>#ifdef __LIBAO__#include <ao/ao.h>#include <pthread.h>#include <signal.h>#endif#include "../asm_call.h"#include "../cfg.h"#ifdef __LIBAO__static pthread_t audio_thread;static pthread_mutex_t audio_mutex;static pthread_cond_t audio_wait;static ao_device *audio_device = 0;static volatile unsigned int samples_waiting = 0;#endifunsigned char *sdl_audio_buffer = 0;int sdl_audio_buffer_len = 0, sdl_audio_buffer_fill = 0;int sdl_audio_buffer_head = 0, sdl_audio_buffer_tail = 0;unsigned char sound_sdl = false;int SoundEnabled = 1;unsigned char PrevStereoSound;unsigned int PrevSoundQuality;#define SAMPLE_NTSC_HI_SCALE 995ULL#define SAMPLE_NTSC_LO 59649ULL#define SAMPLE_PAL_HI_SCALE  1ULL#define SAMPLE_PAL_LO       50ULLstatic const int freqtab[7] = { 8000, 11025, 22050, 44100, 16000, 32000, 48000 };#define RATE freqtab[SoundQuality = ((SoundQuality > 6) ? 1 : SoundQuality)]struct{  unsigned long long hi;  unsigned long long lo;  unsigned long long balance;} sample_control;void InitSampleControl(){  extern unsigned char romispal;  if (romispal)  {    sample_control.hi = SAMPLE_PAL_HI_SCALE*RATE;    sample_control.lo = SAMPLE_PAL_LO;  }  else  {    sample_control.hi = SAMPLE_NTSC_HI_SCALE*RATE;    sample_control.lo = SAMPLE_NTSC_LO;  }  sample_control.balance = sample_control.hi;}#ifdef __LIBAO__static void SoundWriteSamples_ao(unsigned int samples){  extern unsigned int BufferSizeB, BufferSizeW;  extern int DSPBuffer[1280];  void ProcessSoundBuffer();  short stemp[1280];  int *d = DSPBuffer, *end_d = 0;  short *p = stemp;  while (samples > 1280)  {    SoundWriteSamples_ao(1280);    samples -= 1280;  }  //printf("samples %d\n", samples);  BufferSizeB = samples;  BufferSizeW = samples<<1;  asm_call(ProcessSoundBuffer);  end_d = DSPBuffer+samples;  for (; d < end_d; d++, p++)  {    if ((unsigned int)(*d + 0x7FFF) < 0xFFFF) { *p = *d; continue; }    if (*d > 0x7FFF) { *p = 0x7FFF; }    else { *p = 0x8001; }  }  ao_play(audio_device, (char *)stemp, samples*2);}void SoundWrite_ao(){  unsigned int samples = 0;  if (!pthread_mutex_trylock(&audio_mutex))  {    if (!samples_waiting && sample_control.lo)    {      samples = (unsigned int)((sample_control.balance/sample_control.lo) << StereoSound);      sample_control.balance %= sample_control.lo;      sample_control.balance += sample_control.hi;      samples_waiting = samples;      pthread_cond_broadcast(&audio_wait); //Send signal    }    pthread_mutex_unlock(&audio_mutex);  }  else  {    pthread_cond_broadcast(&audio_wait); //Send signal  }}static void *SoundThread_ao(void *useless){  unsigned int samples;  for (;;)  {    pthread_mutex_lock(&audio_mutex);    //The while() is there to prevent error codes from breaking havoc    while (!samples_waiting)    {      pthread_cond_wait(&audio_wait, &audio_mutex); //Wait for signal    }    samples = samples_waiting;    samples_waiting = 0;    pthread_mutex_unlock(&audio_mutex);    SoundWriteSamples_ao(samples);  }  return(0);}static int SoundInit_ao(){  int driver_id = ao_driver_id(libAoDriver);  if (driver_id < 0) { driver_id = ao_default_driver_id(); }  ao_sample_format driver_format;  driver_format.bits = 16;  driver_format.channels = StereoSound+1;  driver_format.rate = freqtab[SoundQuality = ((SoundQuality > 6) ? 1 : SoundQuality)];  driver_format.byte_format = AO_FMT_LITTLE;  if (audio_device)  {    ao_close(audio_device);  }  else  {    if (pthread_create(&audio_thread, 0, SoundThread_ao, 0))    {      puts("pthread_create() failed.");    }    else if (pthread_mutex_init(&audio_mutex, 0))    {      puts("pthread_mutex_init() failed.");    }    else if (pthread_cond_init(&audio_wait, 0))    {      puts("pthread_cond_init() failed.");    }    InitSampleControl();  }  //ao_option driver_options = { "buf_size", "32768", 0 };  audio_device = ao_open_live(driver_id, &driver_format, 0);  if (audio_device)  {    ao_info *di = ao_driver_info(driver_id);    printf("\nAudio Opened.\nDriver: %s\nChannels: %u\nRate: %u\n\n", di->name, driver_format.channels, driver_format.rate);  }  else  {    SoundEnabled = 0;    puts("Audio Open Failed");    return(false);  }  return(true);}#endifvoid SoundWrite_sdl(){  extern int DSPBuffer[];  extern unsigned char DSPDisable;  extern unsigned int BufferSizeB, BufferSizeW, T36HZEnabled;  // Process sound  BufferSizeB = 256;  BufferSizeW = BufferSizeB+BufferSizeB;  // take care of the things we left behind last time  SDL_LockAudio();  while (sdl_audio_buffer_fill < sdl_audio_buffer_len)  {    short *p = (short*)&sdl_audio_buffer[sdl_audio_buffer_tail];    if (soundon && !DSPDisable) { asm_call(ProcessSoundBuffer); }    if (T36HZEnabled)    {      memset(p, 0, BufferSizeW);    }    else    {      int *d = DSPBuffer, *end_d = DSPBuffer+BufferSizeB;      for (; d < end_d; d++, p++)      {        if ((unsigned int)(*d + 0x7fff) < 0xffff) { *p = *d; continue; }        if (*d > 0x7fff) { *p = 0x7fff; }        else { *p = 0x8001; }      }    }    sdl_audio_buffer_fill += BufferSizeW;    sdl_audio_buffer_tail += BufferSizeW;    if (sdl_audio_buffer_tail >= sdl_audio_buffer_len) { sdl_audio_buffer_tail = 0; }  }  SDL_UnlockAudio();}static void SoundUpdate_sdl(void *userdata, unsigned char *stream, int len){  int left = sdl_audio_buffer_len - sdl_audio_buffer_head;  if (left > 0)  {    if (left <= len)    {      memcpy(stream, &sdl_audio_buffer[sdl_audio_buffer_head], left);      stream += left;      len -= left;      sdl_audio_buffer_head = 0;      sdl_audio_buffer_fill -= left;    }    if (len)    {      memcpy(stream, &sdl_audio_buffer[sdl_audio_buffer_head], len);      sdl_audio_buffer_head += len;      sdl_audio_buffer_fill -= len;    }  }}static int SoundInit_sdl(){  const int samptab[7] = { 1, 1, 2, 4, 2, 4, 4 };  SDL_AudioSpec audiospec;  SDL_AudioSpec wanted;  SDL_CloseAudio();  if (sdl_audio_buffer)  {    free(sdl_audio_buffer);    sdl_audio_buffer = 0;  }  sdl_audio_buffer_len = 0;  wanted.freq = RATE;  wanted.channels = StereoSound+1;  wanted.samples = samptab[SoundQuality] * 128 * wanted.channels;  wanted.format = AUDIO_S16LSB;  wanted.userdata = 0;  wanted.callback = SoundUpdate_sdl;  if (SDL_OpenAudio(&wanted, &audiospec) < 0)  {    SoundEnabled = 0;    return(false);  }  SDL_PauseAudio(0);  sdl_audio_buffer_len = audiospec.size*2;  sdl_audio_buffer_len = (sdl_audio_buffer_len + 255) & ~255; // Align to SPCSize  if (!(sdl_audio_buffer = malloc(sdl_audio_buffer_len)))  {    SDL_CloseAudio();    puts("Audio Open Failed");    SoundEnabled = 0;    return(false);  }  sound_sdl = true;  printf("\nAudio Opened.\nDriver: Simple DirectMedia Layer output\nChannels: %u\nRate: %u\n\n", wanted.channels, wanted.freq);  return(true);}int InitSound(){  sound_sdl = false;  if (!SoundEnabled)  {    return(false);  }  PrevSoundQuality = SoundQuality;  PrevStereoSound = StereoSound;  #ifdef __LIBAO__  if (strcmp(libAoDriver, "sdl") && !(!strcmp(libAoDriver, "auto") && !strcmp(ao_driver_info(ao_default_driver_id())->name, "null")))  {    return(SoundInit_ao());  }  #endif  return(SoundInit_sdl());}void DeinitSound(){  #ifdef __LIBAO__  if (audio_device)  {    pthread_kill(audio_thread, SIGTERM);    pthread_mutex_destroy(&audio_mutex);    pthread_cond_destroy(&audio_wait);    ao_close(audio_device);  }  #endif  SDL_CloseAudio();  if (sdl_audio_buffer) { free(sdl_audio_buffer); }}

⌨️ 快捷键说明

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