basic audio stream.
This commit is contained in:
parent
36a428bcea
commit
e0fc6123fc
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -8,3 +8,6 @@
|
||||
[submodule "deps/SDL_ttf"]
|
||||
path = deps/SDL_ttf
|
||||
url = https://github.com/libsdl-org/SDL_ttf.git
|
||||
[submodule "deps/portaudio"]
|
||||
path = deps/portaudio
|
||||
url = https://github.com/PortAudio/portaudio.git
|
||||
|
@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.10)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
add_subdirectory(deps/SDL)
|
||||
add_subdirectory(deps/SDL_ttf)
|
||||
add_subdirectory(deps/portaudio)
|
||||
add_subdirectory(lib/)
|
||||
add_subdirectory(gbemu/)
|
||||
add_subdirectory(deps/check/)
|
||||
|
1
deps/portaudio
vendored
Submodule
1
deps/portaudio
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit aa1cfb046f93b18db4d12986ddbff84cbaa952cb
|
14
include/audio.h
Normal file
14
include/audio.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <common.h>
|
||||
|
||||
typedef struct {
|
||||
float sq1_freq;
|
||||
float sq1_duty;
|
||||
float sq1_amp;
|
||||
float sq2_freq;
|
||||
float sq2_duty;
|
||||
float sq2_amp;
|
||||
} audio_context;
|
||||
|
||||
void audio_init();
|
@ -2,5 +2,5 @@ cmake_minimum_required(VERSION 3.10)
|
||||
project(Lib)
|
||||
file(GLOB SRCS *.c)
|
||||
add_library(Lib STATIC ${SRCS})
|
||||
target_include_directories(Lib PUBLIC ../include ../deps/SDL/include ../deps/SDL_ttf)
|
||||
target_link_libraries(Lib SDL2-static SDL2_ttf::SDL2_ttf-static)
|
||||
target_include_directories(Lib PUBLIC ../include ../deps/SDL/include ../deps/SDL_ttf ../deps/portaudio/include)
|
||||
target_link_libraries(Lib SDL2-static SDL2_ttf::SDL2_ttf-static portaudio)
|
119
lib/audio.c
Normal file
119
lib/audio.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include <audio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
#define SAMPLE_RATE 44100
|
||||
#define FRAMES_PER_BUFFER 64
|
||||
#define TABLE_SIZE 44100
|
||||
|
||||
#define M_PI 3.14159265
|
||||
|
||||
static float sine[TABLE_SIZE];
|
||||
static unsigned long ind = 0;
|
||||
static unsigned long ind2 = 0;
|
||||
|
||||
static int sq1_on_time;
|
||||
static int sq1_off_time;
|
||||
static float sq1 = 1;
|
||||
static int sq1_timer = 0;
|
||||
|
||||
static int sq2_on_time;
|
||||
static int sq2_off_time;
|
||||
static float sq2 = 1;
|
||||
static int sq2_timer = 0;
|
||||
|
||||
static audio_context ctx;
|
||||
|
||||
static int audio_callback(const void* input_uffer, void *output_buffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo *time_info,
|
||||
PaStreamCallbackFlags status_flags,
|
||||
void *userData ) {
|
||||
//printf("Audio Callback!\n");
|
||||
audio_context *ctx = (audio_context *) userData;
|
||||
float *out = (float *)output_buffer;
|
||||
PaTime time = time_info->currentTime;
|
||||
sq1_on_time = 1/(ctx->sq1_freq/(float)SAMPLE_RATE) * ctx->sq1_duty;
|
||||
sq1_off_time = 1/(ctx->sq1_freq/(float)SAMPLE_RATE) * (1 - ctx->sq1_duty);
|
||||
|
||||
sq2_on_time = 1/(ctx->sq2_freq/(float)SAMPLE_RATE) * ctx->sq2_duty;
|
||||
sq2_off_time = 1/(ctx->sq2_freq/(float)SAMPLE_RATE) * (1 - ctx->sq2_duty);
|
||||
for(int i = 0; i < framesPerBuffer; i++) {
|
||||
float val = 0;
|
||||
//handle audio channels
|
||||
//val += 0.2 * sine[ind];
|
||||
//ind += 500;
|
||||
if((sq1_timer >= sq1_on_time && sq1 == 1)) {
|
||||
sq1 = 0;
|
||||
sq1_timer = 0;
|
||||
} else if((sq1_timer >= sq1_off_time && sq1 == 0)){
|
||||
sq1 = 1;
|
||||
sq1_timer = 0;
|
||||
}
|
||||
sq1_timer++;
|
||||
val += ctx->sq1_amp * sq1;
|
||||
|
||||
if((sq2_timer >= sq2_on_time && sq2 == 1)) {
|
||||
sq2 = 0;
|
||||
sq2_timer = 0;
|
||||
} else if((sq2_timer >= sq2_off_time && sq2 == 0)){
|
||||
sq2 = 1;
|
||||
sq2_timer = 0;
|
||||
}
|
||||
sq2_timer++;
|
||||
val += ctx->sq2_amp * sq2;
|
||||
//val += 0.2 * sine[ind2];
|
||||
//ind2 += 200;
|
||||
if(ind >= TABLE_SIZE) ind -= TABLE_SIZE;
|
||||
if(ind2 >= TABLE_SIZE) ind2 -= TABLE_SIZE;
|
||||
*out++ = val;
|
||||
}
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
void audio_init(){
|
||||
PaStreamParameters output_parameters;
|
||||
PaStream *stream;
|
||||
PaError err;
|
||||
|
||||
ctx.sq1_amp = 0;
|
||||
ctx.sq1_duty = 0;
|
||||
ctx.sq1_freq = 0;
|
||||
|
||||
ctx.sq2_amp = 0;
|
||||
ctx.sq2_duty = 0;
|
||||
ctx.sq2_freq = 0;
|
||||
|
||||
for(int i = 0; i < TABLE_SIZE; i++) {
|
||||
sine[i] = (float) sin(((double)i/(double)TABLE_SIZE) * M_PI * 2.);
|
||||
}
|
||||
|
||||
err = Pa_Initialize();
|
||||
if (err != paNoError) goto error;
|
||||
output_parameters.device = Pa_GetDefaultOutputDevice();
|
||||
if(output_parameters.device == paNoDevice) {
|
||||
fprintf(stderr, "No default audio device!\n");
|
||||
goto error;
|
||||
}
|
||||
output_parameters.channelCount = 1;
|
||||
output_parameters.sampleFormat = paFloat32;
|
||||
output_parameters.suggestedLatency = Pa_GetDeviceInfo(output_parameters.device)->defaultLowOutputLatency;
|
||||
output_parameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(&stream,
|
||||
NULL,
|
||||
&output_parameters,
|
||||
SAMPLE_RATE,
|
||||
FRAMES_PER_BUFFER,
|
||||
NULL,
|
||||
audio_callback,
|
||||
&ctx);
|
||||
if(err != paNoError) goto error;
|
||||
err = Pa_StartStream(stream);
|
||||
if(err != paNoError) goto error;
|
||||
return;
|
||||
error:
|
||||
Pa_Terminate();
|
||||
fprintf(stderr, "portaudio stream error\n\tError Number: %d\n\tError Message: %s\n", err, Pa_GetErrorText(err));
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
#include <timer.h>
|
||||
#include <dma.h>
|
||||
#include <ppu.h>
|
||||
#include <audio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
@ -25,6 +26,7 @@ DWORD WINAPI cpu_run(void *p) {
|
||||
ppu_init();
|
||||
timer_init();
|
||||
cpu_init();
|
||||
audio_init();
|
||||
|
||||
ctx.running = true;
|
||||
ctx.paused = false;
|
||||
|
@ -260,7 +260,6 @@ void pipeline_push_pixel() {
|
||||
ppu_get_context()->rendering_window = true;
|
||||
pipeline_fifo_reset();
|
||||
ppu_get_context()->pfc.cur_fetch_state = FS_TILE;
|
||||
printf("Window X: %d\n", lcd_get_context()->win_x);
|
||||
ppu_get_context()->pfc.fetch_x = 0;
|
||||
ppu_get_context()->pfc.fifo_x = 0;
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user