Add copyright message to gles_video
[gpsp.git] / sound.c
diff --git a/sound.c b/sound.c
index 44177ff..81f1fa6 100644 (file)
--- a/sound.c
+++ b/sound.c
@@ -25,29 +25,32 @@ u32 global_enable_audio = 1;
 direct_sound_struct direct_sound_channel[2];
 gbc_sound_struct gbc_sound_channel[4];
 
-#if defined(GP2X_BUILD) || defined(TAVI_BUILD)
-u32 sound_frequency = 44100;
+#ifdef RPI_BUILD
+u32 sound_frequency = 22050;
 #else
 u32 sound_frequency = 44100;
 #endif
 
-SDL_AudioSpec sound_settings;
 SDL_mutex *sound_mutex;
-SDL_cond *sound_cv;
+static SDL_cond *sound_cv;
 
-#ifndef PSP_BUILD
+#ifdef PSP_BUILD
+u32 audio_buffer_size_number = 1;
+#elif defined(POLLUX_BUILD)
 u32 audio_buffer_size_number = 7;
 #else
-u32 audio_buffer_size_number = 1;
+u32 audio_buffer_size_number = 8;
 #endif
 
-u32 audio_buffer_size;
-u32 sound_on = 0;
-s16 sound_buffer[BUFFER_SIZE];
-u32 sound_buffer_base = 0;
+u32 sound_on;
+static u32 audio_buffer_size;
+static s16 sound_buffer[BUFFER_SIZE];
+static u32 sound_buffer_base;
+
+static u32 sound_last_cpu_ticks;
+static fixed16_16 gbc_sound_tick_step;
 
-u32 sound_last_cpu_ticks = 0;
-fixed16_16 gbc_sound_tick_step;
+static u32 sound_exit_flag;
 
 // Queue 1, 2, or 4 samples to the top of the DS FIFO, wrap around circularly
 
@@ -87,31 +90,31 @@ void sound_timer_queue32(u32 channel, u32 value)
 
 #define render_sample_left()                                                  \
   sound_buffer[buffer_index] += current_sample +                              \
-   fp16_16_to_u32((next_sample - current_sample) * fifo_fractional)           \
+   fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8))    \
 
 #define render_sample_right()                                                 \
   sound_buffer[buffer_index + 1] += current_sample +                          \
-   fp16_16_to_u32((next_sample - current_sample) * fifo_fractional)           \
+   fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8))    \
 
 #define render_sample_both()                                                  \
   dest_sample = current_sample +                                              \
-   fp16_16_to_u32((next_sample - current_sample) * fifo_fractional);          \
+   fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8));   \
   sound_buffer[buffer_index] += dest_sample;                                  \
   sound_buffer[buffer_index + 1] += dest_sample                               \
 
 #define render_samples(type)                                                  \
-  while(fifo_fractional <= 0xFFFF)                                            \
+  while(fifo_fractional <= 0xFFFFFF)                                          \
   {                                                                           \
     render_sample_##type();                                                   \
     fifo_fractional += frequency_step;                                        \
     buffer_index = (buffer_index + 2) % BUFFER_SIZE;                          \
   }                                                                           \
 
-void sound_timer(fixed16_16 frequency_step, u32 channel)
+void sound_timer(fixed8_24 frequency_step, u32 channel)
 {
   direct_sound_struct *ds = direct_sound_channel + channel;
 
-  fixed16_16 fifo_fractional = ds->fifo_fractional;
+  fixed8_24 fifo_fractional = ds->fifo_fractional;
   u32 buffer_index = ds->buffer_index;
   s16 current_sample, next_sample, dest_sample;
 
@@ -152,7 +155,7 @@ void sound_timer(fixed16_16 frequency_step, u32 channel)
   }
 
   ds->buffer_index = buffer_index;
-  ds->fifo_fractional = fp16_16_fractional_part(fifo_fractional);
+  ds->fifo_fractional = fp8_24_fractional_part(fifo_fractional);
 
   if(((ds->fifo_top - ds->fifo_base) % 32) <= 16)
   {
@@ -267,8 +270,8 @@ u32 gbc_sound_master_volume;
       if(rate > 2048)                                                         \
         rate = 2048;                                                          \
                                                                               \
-      frequency_step = float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) /  \
-       sound_frequency);                                                      \
+      frequency_step = float_to_fp16_16(((131072.0f / (2048 - rate)) * 8.0f)  \
+       / sound_frequency);                                                    \
                                                                               \
       gs->frequency_step = frequency_step;                                    \
       gs->rate = rate;                                                        \
@@ -312,13 +315,6 @@ u32 gbc_sound_master_volume;
 
 #define update_tone_noenvelope()                                              \
 
-#define gbc_sound_synchronize()                                               \
-  while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >        \
-   (audio_buffer_size * 2))                                                   \
-  {                                                                           \
-    SDL_CondWait(sound_cv, sound_mutex);                                      \
-  }                                                                           \
-
 #define update_tone_counters(envelope_op, sweep_op)                           \
   tick_counter += gbc_sound_tick_step;                                        \
   if(tick_counter > 0xFFFF)                                                   \
@@ -431,19 +427,10 @@ u32 gbc_sound_master_volume;
     wave_bank[i2 + 1] = ((current_sample & 0x0F) - 8);                        \
   }                                                                           \
 
-void synchronize_sound()
-{
-  SDL_LockMutex(sound_mutex);
-
-  gbc_sound_synchronize();
-
-  SDL_UnlockMutex(sound_mutex);
-}
-
 void update_gbc_sound(u32 cpu_ticks)
 {
-  fixed16_16 buffer_ticks = float_to_fp16_16(((float)(cpu_ticks -
-   gbc_sound_last_cpu_ticks) * sound_frequency) / 16777216.0);
+  fixed16_16 buffer_ticks = float_to_fp16_16((float)(cpu_ticks -
+   gbc_sound_last_cpu_ticks) * sound_frequency / GBC_BASE_RATE);
   u32 i, i2;
   gbc_sound_struct *gs = gbc_sound_channel;
   fixed16_16 sample_index, frequency_step;
@@ -469,8 +456,8 @@ void update_gbc_sound(u32 cpu_ticks)
   SDL_LockMutex(sound_mutex);
   if(synchronize_flag)
   {
-    if(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
-     (audio_buffer_size * 3 / 2))
+    if(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >=
+     (audio_buffer_size * 2))
     {
       while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
        (audio_buffer_size * 3 / 2))
@@ -485,13 +472,10 @@ void update_gbc_sound(u32 cpu_ticks)
         real_frame_count = 0;
         virtual_frame_count = 0;
       }
-#endif
-
-/*
-
-#ifdef GP2X_BUILD
+#else
       if(current_frameskip_type == auto_frameskip)
       {
+/*
         u64 current_ticks;
         u64 next_ticks;
         get_ticks_us(&current_ticks);
@@ -500,12 +484,13 @@ void update_gbc_sound(u32 cpu_ticks)
         delay_us(next_ticks - current_ticks);
 
         get_ticks_us(&frame_count_initial_timestamp);
-        real_frame_count = 0;
-        virtual_frame_count = 0;
+*/
+        /* prevent frameskip, or it will cause more audio,
+        * then more waiting here, then frame skip again, ... */
+        num_skipped_frames = 100;
       }
 #endif
 
-*/
     }
   }
   if(sound_on == 1)
@@ -628,7 +613,7 @@ void sound_callback(void *userdata, Uint8 *stream, int length)
   SDL_LockMutex(sound_mutex);
 
   while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) <
-   length)
+   length && !sound_exit_flag)
   {
     SDL_CondWait(sound_cv, sound_mutex);
   }
@@ -710,10 +695,12 @@ void reset_sound()
   gbc_sound_struct *gs = gbc_sound_channel;
   u32 i;
 
+  SDL_LockMutex(sound_mutex);
+
   sound_on = 0;
   sound_buffer_base = 0;
   sound_last_cpu_ticks = 0;
-  memset(sound_buffer, 0, audio_buffer_size);
+  memset(sound_buffer, 0, sizeof(sound_buffer));
 
   for(i = 0; i < 2; i++, ds++)
   {
@@ -741,6 +728,8 @@ void reset_sound()
     gs->sample_data = square_pattern_duty[2];
     gs->active_flag = 0;
   }
+
+  SDL_UnlockMutex(sound_mutex);
 }
 
 void sound_exit()
@@ -748,18 +737,26 @@ void sound_exit()
   gbc_sound_buffer_index =
    (sound_buffer_base + audio_buffer_size) % BUFFER_SIZE;
   SDL_PauseAudio(1);
+  sound_exit_flag = 1;
   SDL_CondSignal(sound_cv);
+  SDL_CloseAudio();
+  SDL_Delay(200);
+  SDL_DestroyMutex(sound_mutex);
+  sound_mutex = NULL;
+  SDL_DestroyCond(sound_cv);
+  sound_cv = NULL;
 }
 
-void init_sound()
+void init_sound(int need_reset)
 {
+  SDL_AudioSpec sound_settings;
+
+  sound_exit_flag = 0;
 #ifdef PSP_BUILD
   audio_buffer_size = (audio_buffer_size_number * 1024) + 3072;
-#elif defined(TAVI_BUILD) || defined(ARM_ARCH)
+#else
   audio_buffer_size = 16 << audio_buffer_size_number;
 //  audio_buffer_size = 16384;
-#else
-  audio_buffer_size = 16384;
 #endif
 
   SDL_AudioSpec desired_spec =
@@ -775,18 +772,28 @@ void init_sound()
     NULL
   };
 
+  sound_mutex = SDL_CreateMutex();
+  sound_cv = SDL_CreateCond();
+
+  SDL_OpenAudio(&desired_spec, &sound_settings);
+  sound_frequency = sound_settings.freq;
+  audio_buffer_size = sound_settings.size;
+  u32 i = audio_buffer_size / 16;
+  for (audio_buffer_size_number = 0; i && (i & 1) == 0; i >>= 1)
+    audio_buffer_size_number++;
+#ifndef PSP_BUILD
+  printf("audio: freq %d, size %d\n", sound_frequency, audio_buffer_size);
+#endif
+
   gbc_sound_tick_step =
-   float_to_fp16_16(256.0 / sound_frequency);
+   float_to_fp16_16(256.0f / sound_frequency);
 
   init_noise_table(noise_table15, 32767, 14);
   init_noise_table(noise_table7, 127, 6);
 
-  reset_sound();
+  if (need_reset)
+    reset_sound();
 
-  SDL_OpenAudio(&desired_spec, &sound_settings);
-  sound_frequency = sound_settings.freq;
-  sound_mutex = SDL_CreateMutex();
-  sound_cv = SDL_CreateCond();
   SDL_PauseAudio(0);
 }