📄 sound.c
字号:
/* 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 + -