dont understand audio :(

This commit is contained in:
Samuel Walker 2025-02-02 22:56:07 -07:00
parent 8493ff5fea
commit d4c6f05fb8
Signed by: piwalker
GPG Key ID: 616B1928705EA4C9
5 changed files with 89 additions and 45 deletions

View File

@ -40,7 +40,7 @@ typedef struct {
u8 sq1_env_pace; u8 sq1_env_pace;
u8 sq1_env_timer; u8 sq1_env_timer;
u8 sq1_sweep_step; u8 sq1_sweep_step;
u8 sq1_audio_buffer[4096]; float sq1_audio_buffer[4096];
u32 sq1_write_head; u32 sq1_write_head;
u32 sq1_read_head; u32 sq1_read_head;
@ -59,7 +59,7 @@ typedef struct {
u8 sq2_env_pace; u8 sq2_env_pace;
u8 sq2_env_timer; u8 sq2_env_timer;
u8 sq2_sweep_step; u8 sq2_sweep_step;
u8 sq2_audio_buffer[4096]; float sq2_audio_buffer[4096];
u32 sq2_write_head; u32 sq2_write_head;
u32 sq2_read_head; u32 sq2_read_head;

View File

@ -26,7 +26,8 @@ static int sq2_timer = 0;
static audio_context ctx; static audio_context ctx;
HANDLE mutex; HANDLE data_to_read;
HANDLE data_to_write;
const u8 square_sample[8] = { const u8 square_sample[8] = {
0x0, 0x0,
@ -74,12 +75,20 @@ static int audio_callback(const void* input_uffer, void *output_buffer,
float left = 0; float left = 0;
float right = 0; float right = 0;
for(int i = 0; i < framesPerBuffer; i++) { for(int i = 0; i < framesPerBuffer; i++) {
if(!ctx.audio_enabled) {
*out++ = 0;
*out++ = 0;
continue;
}
if(WaitForSingleObject(data_to_read, INFINITE) == WAIT_TIMEOUT) {
continue;
}
if(ctx.sq1_write_head != ctx.sq1_read_head) { if(ctx.sq1_write_head != ctx.sq1_read_head) {
if(ctx.ch1_left){ if(ctx.ch1_left){
left = (float)(ctx.sq1_volume * ctx.sq1_audio_buffer[ctx.sq1_read_head])/15.0f; //left = ((float)(ctx.sq1_volume * ctx.sq1_audio_buffer[ctx.sq1_read_head])/15.0f) - 0.5f;
} }
if(ctx.ch1_right){ if(ctx.ch1_right){
right = (float)(ctx.sq1_volume * ctx.sq1_audio_buffer[ctx.sq1_read_head])/15.0f; //right = ((float)(ctx.sq1_volume * ctx.sq1_audio_buffer[ctx.sq1_read_head])/15.0f) - 0.5f;
} }
ctx.sq1_read_head++; ctx.sq1_read_head++;
if (ctx.sq1_read_head >= 4096) { if (ctx.sq1_read_head >= 4096) {
@ -87,30 +96,36 @@ static int audio_callback(const void* input_uffer, void *output_buffer,
} }
} }
if(ctx.sq2_write_head != ctx.sq2_read_head) { //if(ctx.sq2_write_head != ctx.sq2_read_head) {
if(ctx.ch2_left){ if(ctx.ch2_left){
left += (float)(ctx.sq2_volume * ctx.sq2_audio_buffer[ctx.sq2_read_head])/15.0f; left = ctx.sq2_audio_buffer[ctx.sq2_read_head];
} //printf("audio: %d\n", ctx.sq2_audio_buffer[ctx.sq2_read_head]);
if(ctx.ch2_right){ //left = ((float)(ctx.sq2_volume * square_sample[ctx.sq2_sample])/15.0f) - 0.5f;
right += (float)(ctx.sq2_volume * ctx.sq2_audio_buffer[ctx.sq2_read_head])/15.0f;
}
ctx.sq2_read_head++;
if (ctx.sq2_read_head >= 4096) {
ctx.sq2_read_head = 0;
}
} }
if(ctx.ch2_right){
//right += ((float)(ctx.sq2_volume * ctx.sq2_audio_buffer[ctx.sq2_read_head])/15.0f) - 0.5f;
}
ctx.sq2_read_head++;
if (ctx.sq2_read_head >= 4096) {
ctx.sq2_read_head = 0;
}
//}
left *= (float)ctx.volume_left/8.0f; left *= (float)ctx.volume_left/8.0f;
right *= (float)ctx.volume_right/8.0f; right *= (float)ctx.volume_right/8.0f;
*out++ = left; *out++ = left;
*out++ = right; *out++ = right;
ReleaseSemaphore(data_to_write, 1, NULL);
} }
return paContinue; return paContinue;
} }
const int semaphore_count = 128;
static PaStream *stream;
void audio_init(){ void audio_init(){
mutex = CreateMutex(NULL, FALSE, NULL); data_to_read = CreateSemaphore(NULL, 0, semaphore_count, NULL);
data_to_write = CreateSemaphore(NULL, semaphore_count, semaphore_count, NULL);
PaStreamParameters output_parameters; PaStreamParameters output_parameters;
PaStream *stream;
PaError err; PaError err;
ctx.sq1_volume = 1; ctx.sq1_volume = 1;
@ -120,14 +135,21 @@ void audio_init(){
ctx.sq2_volume = 1; ctx.sq2_volume = 1;
ctx.sq2_duty = 0.5; ctx.sq2_duty = 0.5;
ctx.sq2_freq = 400; ctx.sq2_freq = 400;
ctx.audio_enabled = true;
ctx.sq1_period_reset = 0x100; ctx.sq2_period_reset = 0x700;
ctx.sq1_period_timer = 0x100; ctx.sq2_period_timer = 0x700;
ctx.sq2_enable = true;
ctx.sq2_len_enable = false;
ctx.ch2_left = true;
ctx.volume_left = 8;
ctx.sq2_volume = 1;
ctx.sq1_value = -1; ctx.sq1_value = -1;
ctx.sq1_write_head = 0; ctx.sq1_write_head = 0;
ctx.sq1_read_head = 0; ctx.sq1_read_head = 0;
ctx.sq2_read_head = 0; ctx.sq2_read_head = 0;
ctx.sq2_write_head = 0; ctx.sq2_write_head = 0;
ctx.sq2_env_pace = 0;
for(int i = 0; i < TABLE_SIZE; i++) { for(int i = 0; i < TABLE_SIZE; i++) {
sine[i] = (float) sin(((double)i/(double)TABLE_SIZE) * M_PI * 2.); sine[i] = (float) sin(((double)i/(double)TABLE_SIZE) * M_PI * 2.);
@ -150,7 +172,7 @@ void audio_init(){
&output_parameters, &output_parameters,
SAMPLE_RATE, SAMPLE_RATE,
FRAMES_PER_BUFFER, FRAMES_PER_BUFFER,
NULL, paClipOff,
audio_callback, audio_callback,
&ctx); &ctx);
if(err != paNoError) goto error; if(err != paNoError) goto error;
@ -180,7 +202,6 @@ void audio_tick(){
ctx.sq2_len++; ctx.sq2_len++;
if(ctx.sq2_len >= 64) { if(ctx.sq2_len >= 64) {
ctx.sq2_enable = false; ctx.sq2_enable = false;
printf("sq2 timer");
} }
} }
} }
@ -214,12 +235,18 @@ void audio_tick(){
} }
static u32 updates; static u32 updates;
static u32 last;
void audio_period_tick(){ void audio_period_tick(){
updates++;
//DWORD dwaitResult = WaitForSingleObject(mutex, INFINITE); //DWORD dwaitResult = WaitForSingleObject(mutex, INFINITE);
//if(dwaitResult == WAIT_ABANDONED) //if(dwaitResult == WAIT_ABANDONED)
// return; // return;
u32 now = get_ticks();
if(now - last >= 1000) {
printf("Updates: %d\n", updates);
updates = 0;
last = now;
}
ctx.sq1_period_timer++; ctx.sq1_period_timer++;
ctx.sq2_period_timer++; ctx.sq2_period_timer++;
@ -235,9 +262,14 @@ void audio_period_tick(){
ctx.sq2_sample = (ctx.sq2_sample + 1) % 8; ctx.sq2_sample = (ctx.sq2_sample + 1) % 8;
//ctx.sq1_value = (float)square_sample[ctx.sq1_sample];///15.0f; //ctx.sq1_value = (float)square_sample[ctx.sq1_sample];///15.0f;
//ctx.ready = true; //ctx.ready = true;
if(ctx.sq2_sample == 0) {
updates++;
}
} }
if(updates >= 24) { DWORD result = WaitForSingleObject(data_to_write, 0);
updates = 0; if(result != WAIT_TIMEOUT) {
//updates++;
//updates = 0;
//u32 read = ctx.read_head; //u32 read = ctx.read_head;
//u32 write = ctx.write_head; //u32 write = ctx.write_head;
//if(read > write) { //if(read > write) {
@ -247,17 +279,24 @@ void audio_period_tick(){
// return; // return;
//} //}
if(ctx.sq1_enable){ if(ctx.sq1_enable){
ctx.sq1_audio_buffer[ctx.sq1_write_head++] = square_sample[ctx.sq1_sample]; ctx.sq1_audio_buffer[ctx.sq1_write_head++] = ((float)(ctx.sq2_volume * square_sample[ctx.sq1_sample])/7.5f) - 1.0f;
if(ctx.sq1_write_head >= 4096) {
ctx.sq1_write_head = 0; } else {
} ctx.sq1_audio_buffer[ctx.sq1_write_head++] = 0x0;
}
if(ctx.sq1_write_head >= 4096) {
ctx.sq1_write_head = 0;
} }
if(ctx.sq2_enable){ if(ctx.sq2_enable){
ctx.sq2_audio_buffer[ctx.sq2_write_head++] = square_sample[ctx.sq2_sample]; ctx.sq2_audio_buffer[ctx.sq2_write_head++] = ((float)(ctx.sq2_volume * (square_sample[ctx.sq2_sample] - .5f))/7.5f);
if(ctx.sq2_write_head >= 4096) { //printf("Audio: %f\n", ctx.sq2_audio_buffer[ctx.sq2_write_head - 1]);
ctx.sq2_write_head = 0; } else {
} ctx.sq2_audio_buffer[ctx.sq2_write_head++] = 0.0f;
} }
if(ctx.sq2_write_head >= 4096) {
ctx.sq2_write_head = 0;
}
ReleaseSemaphore(data_to_read, 1, NULL);
} }
//ReleaseMutex(mutex); //ReleaseMutex(mutex);
} }
@ -269,17 +308,18 @@ void enable_square1() {
} }
ctx.sq1_volume = ctx.sq1_initial_volume; ctx.sq1_volume = ctx.sq1_initial_volume;
ctx.sq1_env_timer = 0; ctx.sq1_env_timer = 0;
} }
void enable_square2() { void enable_square2() {
//ctx.sq2_enable = true; ctx.sq2_enable = true;
if(ctx.sq2_len >= 64) { if(ctx.sq2_len >= 64) {
ctx.sq2_len = ctx.sq2_initial_len; ctx.sq2_len = ctx.sq2_initial_len;
} }
ctx.sq2_volume = ctx.sq2_initial_volume; ctx.sq2_volume = ctx.sq2_initial_volume;
ctx.sq2_env_timer = 0; ctx.sq2_env_timer = 0;
ctx.sq2_sample = 0;
//printf("Channel 2 enabled, Timer: %d\n", ctx.sq2_len_enable);
} }
u8 audio_read(u16 address) { u8 audio_read(u16 address) {
@ -287,6 +327,7 @@ u8 audio_read(u16 address) {
} }
void audio_write(u16 address, u8 value){ void audio_write(u16 address, u8 value){
return;
if(address == 0xFF26) { if(address == 0xFF26) {
ctx.audio_enabled = value & 0x80; ctx.audio_enabled = value & 0x80;
} }
@ -343,6 +384,9 @@ void audio_write(u16 address, u8 value){
ctx.sq2_initial_volume = value >> 4; ctx.sq2_initial_volume = value >> 4;
ctx.sq2_env_direction = value & 0x8; ctx.sq2_env_direction = value & 0x8;
ctx.sq2_env_pace = value * 0b111; ctx.sq2_env_pace = value * 0b111;
if(!ctx.sq2_env_direction && !ctx.sq2_initial_volume) {
ctx.sq2_enable = false;
}
} }
if(address == 0xFF18) { if(address == 0xFF18) {
ctx.sq2_period_reset = (ctx.sq2_period_reset & 0xF0) | value; ctx.sq2_period_reset = (ctx.sq2_period_reset & 0xF0) | value;

View File

@ -48,7 +48,7 @@ void io_write(u16 address, u8 value){
} }
if(address == 0xFF01) { if(address == 0xFF01) {
serial_data[0] = value; serial_data[0] = value;
printf("%c", value); //printf("%c", value);
return; return;
} }

View File

@ -156,14 +156,14 @@ void ppu_mode_hblank() {
u32 frame_time = end - prev_frame_time; u32 frame_time = end - prev_frame_time;
if(frame_time < target_frame_time) { if(frame_time < target_frame_time) {
delay((target_frame_time - frame_time)); //delay((target_frame_time - frame_time));
} }
if (end - start_timer >= 1000) { if (end - start_timer >= 1000) {
u32 fps = frame_count; u32 fps = frame_count;
start_timer = end; start_timer = end;
frame_count = 0; frame_count = 0;
printf("FPS: %ld\n", fps); //printf("FPS: %ld\n", fps);
if(cart_need_save()){ if(cart_need_save()){
cart_battery_save(); cart_battery_save();
} }

View File

@ -15,16 +15,16 @@ void timer_init() {
ctx.div = 0XAC00; ctx.div = 0XAC00;
LARGE_INTEGER freq; LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq); QueryPerformanceFrequency(&freq);
counts_per_cycle = freq.QuadPart / (1 << 19); counts_per_cycle = freq.QuadPart / (1 << 22);
} }
void timer_tick() { void timer_tick() {
//while(now - last < counts_per_cycle){ while(now - last < counts_per_cycle){
// LARGE_INTEGER current; LARGE_INTEGER current;
// QueryPerformanceCounter(&current); QueryPerformanceCounter(&current);
// now = current.QuadPart; now = current.QuadPart;
// //printf("Last-now: %lld, counts: %lld\n", now - last, counts_per_cycle); //printf("Last-now: %lld, counts: %lld\n", now - last, counts_per_cycle);
//} }
last = now; last = now;
u16 prev_div = ctx.div; u16 prev_div = ctx.div;
ctx.div++; ctx.div++;