diff --git a/include/audio.h b/include/audio.h index 1e12e0a..27306af 100644 --- a/include/audio.h +++ b/include/audio.h @@ -40,7 +40,7 @@ typedef struct { u8 sq1_env_pace; u8 sq1_env_timer; u8 sq1_sweep_step; - u8 sq1_audio_buffer[4096]; + float sq1_audio_buffer[4096]; u32 sq1_write_head; u32 sq1_read_head; @@ -59,7 +59,7 @@ typedef struct { u8 sq2_env_pace; u8 sq2_env_timer; u8 sq2_sweep_step; - u8 sq2_audio_buffer[4096]; + float sq2_audio_buffer[4096]; u32 sq2_write_head; u32 sq2_read_head; diff --git a/lib/audio.c b/lib/audio.c index f46a0d4..5e18efa 100644 --- a/lib/audio.c +++ b/lib/audio.c @@ -26,7 +26,8 @@ static int sq2_timer = 0; static audio_context ctx; -HANDLE mutex; +HANDLE data_to_read; +HANDLE data_to_write; const u8 square_sample[8] = { 0x0, @@ -74,12 +75,20 @@ static int audio_callback(const void* input_uffer, void *output_buffer, float left = 0; float right = 0; 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.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){ - 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++; 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.ch2_left){ - left += (float)(ctx.sq2_volume * ctx.sq2_audio_buffer[ctx.sq2_read_head])/15.0f; - } - if(ctx.ch2_right){ - 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.sq2_write_head != ctx.sq2_read_head) { + if(ctx.ch2_left){ + left = ctx.sq2_audio_buffer[ctx.sq2_read_head]; + //printf("audio: %d\n", ctx.sq2_audio_buffer[ctx.sq2_read_head]); + //left = ((float)(ctx.sq2_volume * square_sample[ctx.sq2_sample])/15.0f) - 0.5f; } + 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; right *= (float)ctx.volume_right/8.0f; *out++ = left; *out++ = right; + ReleaseSemaphore(data_to_write, 1, NULL); } return paContinue; } +const int semaphore_count = 128; +static PaStream *stream; + 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; - PaStream *stream; PaError err; ctx.sq1_volume = 1; @@ -120,14 +135,21 @@ void audio_init(){ ctx.sq2_volume = 1; ctx.sq2_duty = 0.5; ctx.sq2_freq = 400; + ctx.audio_enabled = true; - ctx.sq1_period_reset = 0x100; - ctx.sq1_period_timer = 0x100; + ctx.sq2_period_reset = 0x700; + 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_write_head = 0; ctx.sq1_read_head = 0; ctx.sq2_read_head = 0; ctx.sq2_write_head = 0; + ctx.sq2_env_pace = 0; for(int i = 0; i < TABLE_SIZE; i++) { sine[i] = (float) sin(((double)i/(double)TABLE_SIZE) * M_PI * 2.); @@ -150,7 +172,7 @@ void audio_init(){ &output_parameters, SAMPLE_RATE, FRAMES_PER_BUFFER, - NULL, + paClipOff, audio_callback, &ctx); if(err != paNoError) goto error; @@ -180,7 +202,6 @@ void audio_tick(){ ctx.sq2_len++; if(ctx.sq2_len >= 64) { ctx.sq2_enable = false; - printf("sq2 timer"); } } } @@ -214,12 +235,18 @@ void audio_tick(){ } static u32 updates; +static u32 last; void audio_period_tick(){ - updates++; //DWORD dwaitResult = WaitForSingleObject(mutex, INFINITE); //if(dwaitResult == WAIT_ABANDONED) // return; + u32 now = get_ticks(); + if(now - last >= 1000) { + printf("Updates: %d\n", updates); + updates = 0; + last = now; + } ctx.sq1_period_timer++; ctx.sq2_period_timer++; @@ -235,9 +262,14 @@ void audio_period_tick(){ ctx.sq2_sample = (ctx.sq2_sample + 1) % 8; //ctx.sq1_value = (float)square_sample[ctx.sq1_sample];///15.0f; //ctx.ready = true; + if(ctx.sq2_sample == 0) { + updates++; + } } - if(updates >= 24) { - updates = 0; + DWORD result = WaitForSingleObject(data_to_write, 0); + if(result != WAIT_TIMEOUT) { + //updates++; + //updates = 0; //u32 read = ctx.read_head; //u32 write = ctx.write_head; //if(read > write) { @@ -247,17 +279,24 @@ void audio_period_tick(){ // return; //} if(ctx.sq1_enable){ - ctx.sq1_audio_buffer[ctx.sq1_write_head++] = square_sample[ctx.sq1_sample]; - if(ctx.sq1_write_head >= 4096) { - ctx.sq1_write_head = 0; - } + ctx.sq1_audio_buffer[ctx.sq1_write_head++] = ((float)(ctx.sq2_volume * square_sample[ctx.sq1_sample])/7.5f) - 1.0f; + + } 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){ - ctx.sq2_audio_buffer[ctx.sq2_write_head++] = square_sample[ctx.sq2_sample]; - if(ctx.sq2_write_head >= 4096) { - ctx.sq2_write_head = 0; - } + ctx.sq2_audio_buffer[ctx.sq2_write_head++] = ((float)(ctx.sq2_volume * (square_sample[ctx.sq2_sample] - .5f))/7.5f); + //printf("Audio: %f\n", ctx.sq2_audio_buffer[ctx.sq2_write_head - 1]); + } 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); } @@ -269,17 +308,18 @@ void enable_square1() { } ctx.sq1_volume = ctx.sq1_initial_volume; ctx.sq1_env_timer = 0; - } void enable_square2() { - //ctx.sq2_enable = true; + ctx.sq2_enable = true; if(ctx.sq2_len >= 64) { ctx.sq2_len = ctx.sq2_initial_len; } ctx.sq2_volume = ctx.sq2_initial_volume; 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) { @@ -287,6 +327,7 @@ u8 audio_read(u16 address) { } void audio_write(u16 address, u8 value){ + return; if(address == 0xFF26) { ctx.audio_enabled = value & 0x80; } @@ -343,6 +384,9 @@ void audio_write(u16 address, u8 value){ ctx.sq2_initial_volume = value >> 4; ctx.sq2_env_direction = value & 0x8; ctx.sq2_env_pace = value * 0b111; + if(!ctx.sq2_env_direction && !ctx.sq2_initial_volume) { + ctx.sq2_enable = false; + } } if(address == 0xFF18) { ctx.sq2_period_reset = (ctx.sq2_period_reset & 0xF0) | value; diff --git a/lib/io.c b/lib/io.c index 95888e0..f6c9beb 100644 --- a/lib/io.c +++ b/lib/io.c @@ -48,7 +48,7 @@ void io_write(u16 address, u8 value){ } if(address == 0xFF01) { serial_data[0] = value; - printf("%c", value); + //printf("%c", value); return; } diff --git a/lib/ppu_sm.c b/lib/ppu_sm.c index 942fdc0..313e669 100644 --- a/lib/ppu_sm.c +++ b/lib/ppu_sm.c @@ -156,14 +156,14 @@ void ppu_mode_hblank() { u32 frame_time = end - prev_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) { u32 fps = frame_count; start_timer = end; frame_count = 0; - printf("FPS: %ld\n", fps); + //printf("FPS: %ld\n", fps); if(cart_need_save()){ cart_battery_save(); } diff --git a/lib/timer.c b/lib/timer.c index 4e0ae09..eb38ccc 100644 --- a/lib/timer.c +++ b/lib/timer.c @@ -15,16 +15,16 @@ void timer_init() { ctx.div = 0XAC00; LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); - counts_per_cycle = freq.QuadPart / (1 << 19); + counts_per_cycle = freq.QuadPart / (1 << 22); } void timer_tick() { - //while(now - last < counts_per_cycle){ - // LARGE_INTEGER current; - // QueryPerformanceCounter(¤t); - // now = current.QuadPart; - // //printf("Last-now: %lld, counts: %lld\n", now - last, counts_per_cycle); - //} + while(now - last < counts_per_cycle){ + LARGE_INTEGER current; + QueryPerformanceCounter(¤t); + now = current.QuadPart; + //printf("Last-now: %lld, counts: %lld\n", now - last, counts_per_cycle); + } last = now; u16 prev_div = ctx.div; ctx.div++;