/* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: * Copyright (C) 2002 Xodnizel * * 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 */ #include #include #include #include "sdl.h" #ifdef USE_SEXYAL #include "../sexyal/sexyal.h" static SexyAL *Interface; static SexyAL_device *Output; static SexyAL_format format; static SexyAL_buffering buffering; uint32 GetMaxSound(void) { return(buffering.totalsize); } uint32 GetWriteSound(void) { return(Output->CanWrite(Output)); } void WriteSound(int32 *Buffer, int Count) { //printf("%d\n",Output->CanWrite(Output)); Output->Write(Output, Buffer, Count); } int InitSound(FCEUGI *gi) { if(!_sound) return(0); memset(&format,0,sizeof(format)); memset(&buffering,0,sizeof(buffering)); FCEUI_SetSoundVolume(soundvol); FCEUI_SetSoundQuality(soundq); Interface=SexyAL_Init(0); format.sampformat=SEXYAL_FMT_PCMS32S16; format.channels=gi->soundchan?gi->soundchan:1; format.rate=gi->soundrate?gi->soundrate:soundrate; buffering.fragcount=buffering.fragsize=0; buffering.ms=soundbufsize; FCEUI_printf("\nInitializing sound..."); if(!(Output=Interface->Open(Interface,SEXYAL_ID_UNUSED,&format,&buffering))) { FCEUD_PrintError("Error opening a sound device."); Interface->Destroy(Interface); Interface=0; return(0); } if(soundq && format.rate!=48000 && format.rate!=44100 && format.rate!=96000) { FCEUD_PrintError("Set sound playback rate neither 44100, 48000, nor 96000, but needs to be when in high-quality sound mode."); KillSound(); return(0); } if(format.rate<8192 || format.rate > 96000) { FCEUD_PrintError("Set rate is out of range [8192-96000]"); KillSound(); return(0); } FCEUI_printf("\n Bits: %u\n Rate: %u\n Channels: %u\n Byte order: CPU %s\n Buffer size: %u sample frames(%f ms)\n",(format.sampformat>>4)*8,format.rate,format.channels,format.byteorder?"Reversed":"Native",buffering.totalsize,(double)buffering.totalsize*1000/format.rate); format.sampformat=SEXYAL_FMT_PCMS32S16; format.channels=gi->soundchan?gi->soundchan:1; format.byteorder=0; //format.rate=gi->soundrate?gi->soundrate:soundrate; Output->SetConvert(Output,&format); FCEUI_Sound(format.rate); return(1); } void SilenceSound(int n) { } int KillSound(void) { FCEUI_Sound(0); if(Output) Output->Close(Output); if(Interface) Interface->Destroy(Interface); Interface=0; if(!Output) return(0); Output=0; return(1); } #elif USE_JACKACK /* Use JACK Audio Connection Kit */ #include #include static jack_port_t *output_port = NULL; static jack_client_t *client = NULL; static jack_ringbuffer_t *tmpbuf = NULL; static unsigned int BufferSize; static int process(jack_nframes_t nframes, void *arg) { jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer(output_port, nframes); size_t canread; canread = jack_ringbuffer_read_space(tmpbuf) / sizeof(jack_default_audio_sample_t); if(canread > nframes) canread = nframes; jack_ringbuffer_read(tmpbuf, out,canread * sizeof(jack_default_audio_sample_t)); nframes -= canread; if(nframes) /* Buffer underflow. Hmm. */ { } } uint32 GetMaxSound(void) { return(BufferSize); } uint32 GetWriteSound(void) { return(jack_readbuffer_write_space / sizeof(jack_default_audio_sample_t)); } static void DeadSound(void *arg) { puts("AGH! Sound server hates us! Let's go on a rampage."); } int InitSound(FCEUGI *gi) { const char **ports; client = jack_client_new("FCE Ultra"); jack_set_process_callback(client, process, 0); jack_on_shutdown(client, DeadSound, 0); printf("%ld\n",jack_get_sample_rate(client)); output_port = jack_port_register(client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); BufferSize = soundbufsize * soundrate / 1000; tmpbuf = jack_ringbuffer_create(BufferSize * sizeof(jack_default_audio_sample_t)); jack_activate(client); ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); jack_connect(client, jack_port_name(output_port), ports[0]); free(ports); } void WriteSound(int32 *buf, int Count) { jack_default_audio_sample_t jbuf[Count]; int x; for(x=0;x>= 1; while(len) { int16 sample = 0; if(BufferIn) { sample = Buffer[BufferRead]; BufferRead = (BufferRead + 1) % BufferSize; BufferIn--; } else sample = 0; *tmps = sample; tmps++; len--; } } int InitSound(FCEUGI *gi) { SDL_AudioSpec spec; if(!_sound) return(0); memset(&spec,0,sizeof(spec)); if(SDL_InitSubSystem(SDL_INIT_AUDIO)<0) { puts(SDL_GetError()); KillSound(); return(0); } spec.freq = soundrate; spec.format = AUDIO_S16SYS; spec.channels = 1; spec.samples = 256; spec.callback = fillaudio; spec.userdata = 0; BufferSize = soundbufsize * soundrate / 1000; BufferSize -= spec.samples * 2; /* SDL uses at least double-buffering, so multiply by 2. */ if(BufferSize < spec.samples) BufferSize = spec.samples; Buffer = (int *)malloc(sizeof(int) * BufferSize); BufferRead = BufferWrite = BufferIn = 0; //printf("SDL Size: %d, Internal size: %d\n",spec.samples,BufferSize); if(SDL_OpenAudio(&spec,0)<0) { puts(SDL_GetError()); KillSound(); return(0); } SDL_PauseAudio(0); FCEUI_Sound(soundrate); return(1); } uint32 GetMaxSound(void) { return(BufferSize); } uint32 GetWriteSound(void) { return(BufferSize - BufferIn); } void WriteSound(int32 *buf, int Count) { while(Count) { while(BufferIn == BufferSize) SDL_Delay(1); Buffer[BufferWrite] = *buf; Count--; BufferWrite = (BufferWrite + 1) % BufferSize; BufferIn++; buf++; } } void SilenceSound(int n) { SDL_PauseAudio(n); } int KillSound(void) { FCEUI_Sound(0); SDL_CloseAudio(); SDL_QuitSubSystem(SDL_INIT_AUDIO); if(Buffer) { free((void *)Buffer); Buffer = 0; } return(0); } #endif static int mute=0; static int soundvolume=100; void FCEUD_SoundVolumeAdjust(int n) { switch(n) { case -1: soundvolume-=10; if(soundvolume<0) soundvolume=0; break; case 0: soundvolume=100; break; case 1: soundvolume+=10; if(soundvolume>150) soundvolume=150; break; } mute=0; FCEUI_SetSoundVolume(soundvolume); FCEU_DispMessage("Sound volume %d.", soundvolume); } void FCEUD_SoundToggle(void) { if(mute) { mute=0; FCEUI_SetSoundVolume(soundvolume); FCEU_DispMessage("Sound mute off."); } else { mute=1; FCEUI_SetSoundVolume(0); FCEU_DispMessage("Sound mute on."); } }