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

📄 sound.c

📁 psp上的GBA模拟器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* gameplaySP * * Copyright (C) 2006 Exophase <exophase@gmail.com> * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "SDL.h"#include "common.h"u32 global_enable_audio = 1;direct_sound_struct direct_sound_channel[2];gbc_sound_struct gbc_sound_channel[4];u32 sound_frequency = 44100;SDL_AudioSpec sound_settings;SDL_mutex *sound_mutex;SDL_cond *sound_cv;u32 audio_buffer_size_number = 2;u32 audio_buffer_size;u32 sound_on = 0;s16 sound_buffer[BUFFER_SIZE];u32 sound_buffer_base = 0;u32 sound_last_cpu_ticks = 0;fixed16_16 gbc_sound_tick_step;// Queue 1, 2, or 4 samples to the top of the DS FIFO, wrap around circularly#define sound_timer_queue(size, value)                                        \  *((s##size *)(ds->fifo + ds->fifo_top)) = value;                            \  ds->fifo_top = (ds->fifo_top + 1) % 32;                                     \void sound_timer_queue8(u32 channel, u8 value){  direct_sound_struct *ds = direct_sound_channel + channel;  sound_timer_queue(8, value);}void sound_timer_queue16(u32 channel, u16 value){  direct_sound_struct *ds = direct_sound_channel + channel;  sound_timer_queue(8, value & 0xFF);  sound_timer_queue(8, value >> 8);}void sound_timer_queue32(u32 channel, u32 value){  direct_sound_struct *ds = direct_sound_channel + channel;  sound_timer_queue(8, value & 0xFF);  sound_timer_queue(8, (value >> 8) & 0xFF);  sound_timer_queue(8, (value >> 16) & 0xFF);  sound_timer_queue(8, value >> 24);}// Unqueue 1 sample from the base of the DS FIFO and place it on the audio// buffer for as many samples as necessary. If the DS FIFO is 16 bytes or// smaller and if DMA is enabled for the sound channel initiate a DMA transfer// to the DS FIFO.#define render_sample_null()                                                  \#define render_sample_left()                                                  \  sound_buffer[buffer_index] += current_sample +                              \   fp16_16_to_u32((next_sample - current_sample) * fifo_fractional)           \#define render_sample_right()                                                 \  sound_buffer[buffer_index + 1] += current_sample +                          \   fp16_16_to_u32((next_sample - current_sample) * fifo_fractional)           \#define render_sample_both()                                                  \  dest_sample = current_sample +                                              \   fp16_16_to_u32((next_sample - current_sample) * fifo_fractional);          \  sound_buffer[buffer_index] += dest_sample;                                  \  sound_buffer[buffer_index + 1] += dest_sample                               \#define render_samples(type)                                                  \  while(fifo_fractional <= 0xFFFF)                                            \  {                                                                           \    render_sample_##type();                                                   \    fifo_fractional += frequency_step;                                        \    buffer_index = (buffer_index + 2) % BUFFER_SIZE;                          \  }                                                                           \void sound_timer(fixed16_16 frequency_step, u32 channel){  direct_sound_struct *ds = direct_sound_channel + channel;  fixed16_16 fifo_fractional = ds->fifo_fractional;  u32 buffer_index = ds->buffer_index;  s16 current_sample, next_sample, dest_sample;  current_sample = ds->fifo[ds->fifo_base] << 4;  ds->fifo_base = (ds->fifo_base + 1) % 32;  next_sample = ds->fifo[ds->fifo_base] << 4;  if(sound_on == 1)  {    if(ds->volume == DIRECT_SOUND_VOLUME_50)    {      current_sample >>= 1;      next_sample >>= 1;    }    switch(ds->status)    {      case DIRECT_SOUND_INACTIVE:        render_samples(null);        break;      case DIRECT_SOUND_RIGHT:        render_samples(right);        break;      case DIRECT_SOUND_LEFT:        render_samples(left);        break;      case DIRECT_SOUND_LEFTRIGHT:        render_samples(both);        break;    }  }  else  {    render_samples(null);  }  ds->buffer_index = buffer_index;  ds->fifo_fractional = fp16_16_fractional_part(fifo_fractional);  if(((ds->fifo_top - ds->fifo_base) % 32) <= 16)  {    if(dma[1].direct_sound_channel == channel)      dma_transfer(dma + 1);    if(dma[2].direct_sound_channel == channel)      dma_transfer(dma + 2);  }}void sound_reset_fifo(u32 channel){  direct_sound_struct *ds = direct_sound_channel;  memset(ds->fifo, 0, 32);}// Initial pattern data = 4bits (signed)// Channel volume = 12bits// Envelope volume = 14bits// Master volume = 2bits// Recalculate left and right volume as volume changes.// To calculate the current sample, use (sample * volume) >> 16// Square waves range from -8 (low) to 7 (high)s8 square_pattern_duty[4][8] ={  { 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0xF8, 0xF8, 0xF8 },  { 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0x07, 0xF8, 0xF8 },  { 0xF8, 0xF8, 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8 },  { 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8, 0x07, 0x07 },};s8 wave_samples[64];u32 noise_table15[1024];u32 noise_table7[4];u32 gbc_sound_master_volume_table[4] = { 1, 2, 4, 0 };u32 gbc_sound_channel_volume_table[8] ={  fixed_div(0, 7, 12),  fixed_div(1, 7, 12),  fixed_div(2, 7, 12),  fixed_div(3, 7, 12),  fixed_div(4, 7, 12),  fixed_div(5, 7, 12),  fixed_div(6, 7, 12),  fixed_div(7, 7, 12)};u32 gbc_sound_envelope_volume_table[16] ={  fixed_div(0, 15, 14),  fixed_div(1, 15, 14),  fixed_div(2, 15, 14),  fixed_div(3, 15, 14),  fixed_div(4, 15, 14),  fixed_div(5, 15, 14),  fixed_div(6, 15, 14),  fixed_div(7, 15, 14),  fixed_div(8, 15, 14),  fixed_div(9, 15, 14),  fixed_div(10, 15, 14),  fixed_div(11, 15, 14),  fixed_div(12, 15, 14),  fixed_div(13, 15, 14),  fixed_div(14, 15, 14),  fixed_div(15, 15, 14)};u32 gbc_sound_buffer_index = 0;u32 gbc_sound_last_cpu_ticks = 0;u32 gbc_sound_partial_ticks = 0;u32 gbc_sound_master_volume_left;u32 gbc_sound_master_volume_right;u32 gbc_sound_master_volume;#define update_volume_channel_envelope(channel)                               \  volume_##channel = gbc_sound_envelope_volume_table[envelope_volume] *       \   gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] *        \   gbc_sound_master_volume_table[gbc_sound_master_volume]                     \#define update_volume_channel_noenvelope(channel)                             \  volume_##channel = gs->wave_volume *                                        \   gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] *        \   gbc_sound_master_volume_table[gbc_sound_master_volume]                     \#define update_volume(type)                                                   \  update_volume_channel_##type(left);                                         \  update_volume_channel_##type(right)                                         \#define update_tone_sweep()                                                   \  if(gs->sweep_status)                                                        \  {                                                                           \    u32 sweep_ticks = gs->sweep_ticks - 1;                                    \                                                                              \    if(sweep_ticks == 0)                                                      \    {                                                                         \      u32 rate = gs->rate;                                                    \                                                                              \      if(gs->sweep_direction)                                                 \        rate = rate - (rate >> gs->sweep_shift);                              \      else                                                                    \        rate = rate + (rate >> gs->sweep_shift);                              \                                                                              \      if(rate > 2048)                                                         \        rate = 2048;                                                          \                                                                              \      frequency_step = float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) /  \

⌨️ 快捷键说明

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