dont understand audio :(
This commit is contained in:
parent
8493ff5fea
commit
d4c6f05fb8
@ -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;
|
||||||
|
|
||||||
|
110
lib/audio.c
110
lib/audio.c
@ -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;
|
||||||
|
2
lib/io.c
2
lib/io.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
14
lib/timer.c
14
lib/timer.c
@ -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(¤t);
|
QueryPerformanceCounter(¤t);
|
||||||
// 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++;
|
||||||
|
Loading…
Reference in New Issue
Block a user