> compile NEMU
221220000 张三 Linux zzy 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux 14:59:07 up 4 days, 10:04, 1 user, load average: 0.58, 0.47, 0.52
This commit is contained in:
@ -35,14 +35,21 @@ void __am_audio_status(AM_AUDIO_STATUS_T *stat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void __am_audio_play(AM_AUDIO_PLAY_T *ctl) {
|
void __am_audio_play(AM_AUDIO_PLAY_T *ctl) {
|
||||||
for (int i = 0; i < ctl->buf.end - ctl->buf.start; i++) {
|
int cnt = ctl->buf.end - ctl->buf.start, i = 0;
|
||||||
if (inl(AUDIO_COUNT_ADDR) == audio_sbuf_size) {
|
while (cnt) {
|
||||||
i--;
|
// lock sbuf
|
||||||
continue;
|
outl(AUDIO_INIT_ADDR, 1 << 1);
|
||||||
} else {
|
for (; i < cnt; i++) {
|
||||||
outb(AUDIO_SBUF_ADDR + audio_write, ((uint8_t*)ctl->buf.start)[i]);
|
if (inl(AUDIO_COUNT_ADDR) == audio_sbuf_size) {
|
||||||
audio_write = (audio_write + 1) % audio_sbuf_size;
|
i--;
|
||||||
outl(AUDIO_COUNT_ADDR, inl(AUDIO_COUNT_ADDR) + 1);
|
break;
|
||||||
|
} else {
|
||||||
|
outb(AUDIO_SBUF_ADDR + audio_write, ((uint8_t*)ctl->buf.start)[i]);
|
||||||
|
audio_write = (audio_write + 1) % audio_sbuf_size;
|
||||||
|
outl(AUDIO_COUNT_ADDR, inl(AUDIO_COUNT_ADDR) + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// unlock sbuf
|
||||||
|
outl(AUDIO_INIT_ADDR, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include <device/map.h>
|
#include <device/map.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include <stdatomic.h>
|
#include <threads.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
reg_freq,
|
reg_freq,
|
||||||
@ -32,12 +32,14 @@ enum {
|
|||||||
static uint8_t *sbuf = NULL;
|
static uint8_t *sbuf = NULL;
|
||||||
static uint32_t *audio_base = NULL;
|
static uint32_t *audio_base = NULL;
|
||||||
static uint32_t pos_read = 0;
|
static uint32_t pos_read = 0;
|
||||||
static atomic_char32_t audio_count = 0;
|
static uint32_t audio_count = 0;
|
||||||
|
static mtx_t mtx_audio;
|
||||||
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
static void audio_callback(void *userdata, uint8_t *stream, int len) {
|
static void audio_callback(void *userdata, uint8_t *stream, int len) {
|
||||||
uint32_t count = atomic_load(&audio_count);
|
mtx_lock(&mtx_audio);
|
||||||
|
uint32_t count = audio_count;
|
||||||
uint32_t read_cnt = MIN(count, len);
|
uint32_t read_cnt = MIN(count, len);
|
||||||
uint32_t to_end_cnt = CONFIG_SB_SIZE - pos_read;
|
uint32_t to_end_cnt = CONFIG_SB_SIZE - pos_read;
|
||||||
int32_t out_bound_cnt = read_cnt - to_end_cnt;
|
int32_t out_bound_cnt = read_cnt - to_end_cnt;
|
||||||
@ -52,10 +54,14 @@ static void audio_callback(void *userdata, uint8_t *stream, int len) {
|
|||||||
pos_read %= CONFIG_SB_SIZE;
|
pos_read %= CONFIG_SB_SIZE;
|
||||||
// if (len > read_cnt) memset(stream + read_cnt, 0, len - read_cnt);
|
// if (len > read_cnt) memset(stream + read_cnt, 0, len - read_cnt);
|
||||||
count -= read_cnt;
|
count -= read_cnt;
|
||||||
atomic_store(&audio_count, count);
|
audio_count = count;
|
||||||
|
mtx_unlock(&mtx_audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void init_audio_dev() {
|
static inline void init_audio_dev() {
|
||||||
|
int ret = mtx_init(&mtx_audio, mtx_plain);
|
||||||
|
assert(ret == thrd_success);
|
||||||
|
|
||||||
SDL_AudioSpec s = {};
|
SDL_AudioSpec s = {};
|
||||||
s.format = AUDIO_S16SYS; // 假设系统中音频数据的格式总是使用16位有符号数来表示
|
s.format = AUDIO_S16SYS; // 假设系统中音频数据的格式总是使用16位有符号数来表示
|
||||||
s.userdata = NULL; // 不使用
|
s.userdata = NULL; // 不使用
|
||||||
@ -81,14 +87,19 @@ static void audio_io_handler(uint32_t offset, int len, bool is_write) {
|
|||||||
assert(is_write == false);
|
assert(is_write == false);
|
||||||
break;
|
break;
|
||||||
case reg_init:
|
case reg_init:
|
||||||
if (is_write && audio_base[reg_init] != 0) {
|
if (is_write) {
|
||||||
init_audio_dev();
|
if (audio_base[reg_init] & 1) init_audio_dev();
|
||||||
|
if (audio_base[reg_init] & 1 << 1) {
|
||||||
|
mtx_lock(&mtx_audio);
|
||||||
|
} else {
|
||||||
|
mtx_unlock(&mtx_audio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case reg_count:
|
case reg_count:
|
||||||
// TODO: must be add a lock here
|
// TODO: must be add a lock here
|
||||||
if (is_write) atomic_store(&audio_count, audio_base[reg_count]);
|
if (is_write) audio_count = audio_base[reg_count];
|
||||||
else audio_base[reg_count] = atomic_load(&audio_count);
|
else audio_base[reg_count] = audio_count;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
Reference in New Issue
Block a user