📄 sound.c
字号:
if(gs->wave_type == 0) { if(gs->wave_bank == 1) sample_data += 32; gbc_sound_render_channel(samples, 32, noenvelope, nosweep); } else { gbc_sound_render_channel(samples, 64, noenvelope, nosweep); } } gs = gbc_sound_channel + 3; if(gs->active_flag) { sound_status |= 0x08; envelope_volume = gs->envelope_volume; if(gs->noise_type == 1) { gbc_sound_render_channel(noise, half, envelope, nosweep); } else { gbc_sound_render_channel(noise, full, envelope, nosweep); } } } address16(io_registers, 0x84) = sound_status; SDL_CondSignal(sound_cv); SDL_UnlockMutex(sound_mutex); gbc_sound_last_cpu_ticks = cpu_ticks; gbc_sound_buffer_index = (gbc_sound_buffer_index + (buffer_ticks * 2)) % BUFFER_SIZE;}#define sound_copy_normal() \ current_sample = source[i] \#define sound_copy(source_offset, length, render_type) \ _length = (length) / 2; \ source = (s16 *)(sound_buffer + source_offset); \ for(i = 0; i < _length; i++) \ { \ sound_copy_##render_type(); \ if(current_sample > 2047) \ current_sample = 2047; \ if(current_sample < -2048) \ current_sample = -2048; \ \ stream_base[i] = current_sample << 4; \ source[i] = 0; \ } \#define sound_copy_null(source_offset, length) \ _length = (length) / 2; \ source = (s16 *)(sound_buffer + source_offset); \ for(i = 0; i < _length; i++) \ { \ stream_base[i] = 0; \ source[i] = 0; \ } \void sound_callback(void *userdata, Uint8 *stream, int length){ u32 sample_length = length / 2; u32 _length; u32 i; s16 *stream_base = (s16 *)stream; s16 *source; s32 current_sample; SDL_LockMutex(sound_mutex); while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) < length) { SDL_CondWait(sound_cv, sound_mutex); } if(global_enable_audio) { if((sound_buffer_base + sample_length) >= BUFFER_SIZE) { u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2; sound_copy(sound_buffer_base, partial_length, normal); source = (s16 *)sound_buffer; sound_copy(0, length - partial_length, normal); sound_buffer_base = (length - partial_length) / 2; } else { sound_copy(sound_buffer_base, length, normal); sound_buffer_base += sample_length; } } else { if((sound_buffer_base + sample_length) >= BUFFER_SIZE) { u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2; sound_copy_null(sound_buffer_base, partial_length); source = (s16 *)sound_buffer; sound_copy(0, length - partial_length, normal); sound_buffer_base = (length - partial_length) / 2; } else { sound_copy_null(sound_buffer_base, length); sound_buffer_base += sample_length; } } SDL_CondSignal(sound_cv); SDL_UnlockMutex(sound_mutex);}// Special thanks to blarrg for the LSFR frequency used in Meridian, as posted// on the forum at http://meridian.overclocked.org:// http://meridian.overclocked.org/cgi-bin/wwwthreads/showpost.pl?Board=merid// angeneraldiscussion&Number=2069&page=0&view=expanded&mode=threaded&sb=4// Hope you don't mind me borrowing it ^_-void init_noise_table(u32 *table, u32 period, u32 bit_length){ u32 shift_register = 0xFF; u32 mask = ~(1 << bit_length); s32 table_pos, bit_pos; u32 current_entry; u32 table_period = (period + 31) / 32; // Bits are stored in reverse order so they can be more easily moved to // bit 31, for sign extended shift down. for(table_pos = 0; table_pos < table_period; table_pos++) { current_entry = 0; for(bit_pos = 31; bit_pos >= 0; bit_pos--) { current_entry |= (shift_register & 0x01) << bit_pos; shift_register = ((1 & (shift_register ^ (shift_register >> 1))) << bit_length) | ((shift_register >> 1) & mask); } table[table_pos] = current_entry; }}void reset_sound(){ direct_sound_struct *ds = direct_sound_channel; gbc_sound_struct *gs = gbc_sound_channel; u32 i; sound_on = 0; sound_buffer_base = 0; sound_last_cpu_ticks = 0; memset(sound_buffer, 0, audio_buffer_size); for(i = 0; i < 2; i++, ds++) { ds->buffer_index = 0; ds->status = DIRECT_SOUND_INACTIVE; ds->fifo_top = 0; ds->fifo_base = 0; ds->fifo_fractional = 0; ds->last_cpu_ticks = 0; memset(ds->fifo, 0, 32); } gbc_sound_buffer_index = 0; gbc_sound_last_cpu_ticks = 0; gbc_sound_partial_ticks = 0; gbc_sound_master_volume_left = 0; gbc_sound_master_volume_right = 0; gbc_sound_master_volume = 0; memset(wave_samples, 0, 64); for(i = 0; i < 4; i++, gs++) { gs->status = GBC_SOUND_INACTIVE; gs->sample_data = square_pattern_duty[2]; gs->active_flag = 0; }}void sound_exit(){ gbc_sound_buffer_index = (sound_buffer_base + audio_buffer_size) % BUFFER_SIZE; SDL_PauseAudio(1); SDL_CondSignal(sound_cv);}void init_sound(){#ifdef PSP_BUILD audio_buffer_size = (audio_buffer_size_number * 1024) + 2048;#else audio_buffer_size = 16384;#endif SDL_AudioSpec desired_spec = { sound_frequency, AUDIO_S16, 2, 0, audio_buffer_size / 4, 0, 0, sound_callback, NULL }; gbc_sound_tick_step = float_to_fp16_16(256.0 / sound_frequency); init_noise_table(noise_table15, 32767, 14); init_noise_table(noise_table7, 127, 6); reset_sound(); SDL_OpenAudio(&desired_spec, &sound_settings); sound_frequency = sound_settings.freq; sound_mutex = SDL_CreateMutex(); sound_cv = SDL_CreateCond(); SDL_PauseAudio(0);}#define sound_savestate_builder(type) \void sound_##type##_savestate(file_tag_type savestate_file) \{ \ file_##type##_variable(savestate_file, sound_on); \ file_##type##_variable(savestate_file, sound_buffer_base); \ file_##type##_variable(savestate_file, sound_last_cpu_ticks); \ file_##type##_variable(savestate_file, gbc_sound_buffer_index); \ file_##type##_variable(savestate_file, gbc_sound_last_cpu_ticks); \ file_##type##_variable(savestate_file, gbc_sound_partial_ticks); \ file_##type##_variable(savestate_file, gbc_sound_master_volume_left); \ file_##type##_variable(savestate_file, gbc_sound_master_volume_right); \ file_##type##_variable(savestate_file, gbc_sound_master_volume); \ file_##type##_array(savestate_file, wave_samples); \ file_##type##_array(savestate_file, direct_sound_channel); \ file_##type##_array(savestate_file, gbc_sound_channel); \} \sound_savestate_builder(read);sound_savestate_builder(write_mem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -