wav支持(没有测试)

This commit is contained in:
2026-04-16 20:04:22 +08:00
parent 643b26cfb2
commit 4eae6c34c4
15 changed files with 714 additions and 3 deletions

View File

@@ -362,7 +362,7 @@ set(RAMDISK_ROOT_APPS)
set(USER_SHELL_COMMAND_APPS
help ls cat pwd cd exec pid spawn wait sleep yield
shutdown restart exit clear ansi ansitest fastfetch memstat fsstat taskstat userstat
shutdown restart exit clear ansi ansitest wavplay fastfetch memstat fsstat taskstat userstat
shstat stats tty dmesg kbdstat mkdir touch write append cp mv grep rm
)

View File

@@ -10,6 +10,7 @@ static int ush_cmd_help(void) {
ush_writeln(" exec|run <path|name>");
ush_writeln(" clear");
ush_writeln(" ansi / ansitest / color");
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
ush_writeln(" fastfetch [--plain]");
ush_writeln(" memstat / fsstat / taskstat / userstat / shstat / stats");
ush_writeln(" tty [index]");
@@ -78,4 +79,3 @@ int cleonos_app_main(void) {
return (success != 0) ? 0 : 1;
}

View File

@@ -134,6 +134,7 @@ static int ush_cmd_help(void) {
ush_writeln(" exec|run <path|name>");
ush_writeln(" clear");
ush_writeln(" ansi / ansitest / color");
ush_writeln(" wavplay <file.wav> [steps] [ticks] / wavplay --stop");
ush_writeln(" fastfetch [--plain]");
ush_writeln(" memstat / fsstat / taskstat / userstat / shstat / stats");
ush_writeln(" tty [index]");

View File

@@ -0,0 +1,495 @@
#include "cmd_runtime.h"
#define USH_WAVPLAY_FILE_MAX 65536ULL
#define USH_WAVPLAY_DEFAULT_STEPS 256ULL
#define USH_WAVPLAY_MAX_STEPS 4096ULL
#define USH_WAVPLAY_DEFAULT_TICKS 1ULL
#define USH_WAVPLAY_MAX_TICKS 64ULL
#define USH_WAVPLAY_RUN_TICK_MAX 512ULL
typedef struct ush_wav_info {
const unsigned char *data;
u64 data_size;
u64 frame_count;
u64 sample_rate;
u64 channels;
u64 bits_per_sample;
u64 block_align;
} ush_wav_info;
static unsigned char ush_wavplay_file_buf[USH_WAVPLAY_FILE_MAX + 1ULL];
static unsigned int ush_wav_le16(const unsigned char *ptr) {
return (unsigned int)ptr[0] | ((unsigned int)ptr[1] << 8U);
}
static unsigned int ush_wav_le32(const unsigned char *ptr) {
return (unsigned int)ptr[0] |
((unsigned int)ptr[1] << 8U) |
((unsigned int)ptr[2] << 16U) |
((unsigned int)ptr[3] << 24U);
}
static int ush_wav_tag_eq(const unsigned char *tag, const char *lit4) {
if (tag == (const unsigned char *)0 || lit4 == (const char *)0) {
return 0;
}
return (tag[0] == (unsigned char)lit4[0] &&
tag[1] == (unsigned char)lit4[1] &&
tag[2] == (unsigned char)lit4[2] &&
tag[3] == (unsigned char)lit4[3])
? 1
: 0;
}
static void ush_wavplay_write_u64_dec(u64 value) {
char rev[32];
u64 len = 0ULL;
if (value == 0ULL) {
ush_write_char('0');
return;
}
while (value > 0ULL && len < (u64)sizeof(rev)) {
rev[len++] = (char)('0' + (value % 10ULL));
value /= 10ULL;
}
while (len > 0ULL) {
len--;
ush_write_char(rev[len]);
}
}
static void ush_wavplay_print_meta(const char *path, const ush_wav_info *info, u64 steps, u64 ticks) {
ush_write("wavplay: ");
ush_writeln(path);
ush_write(" sample_rate=");
ush_wavplay_write_u64_dec(info->sample_rate);
ush_write("Hz channels=");
ush_wavplay_write_u64_dec(info->channels);
ush_write(" bits=");
ush_wavplay_write_u64_dec(info->bits_per_sample);
ush_write(" frames=");
ush_wavplay_write_u64_dec(info->frame_count);
ush_write_char('\n');
ush_write(" play_steps=");
ush_wavplay_write_u64_dec(steps);
ush_write(" ticks_per_step=");
ush_wavplay_write_u64_dec(ticks);
ush_write_char('\n');
}
static int ush_wav_parse(const unsigned char *buffer, u64 size, ush_wav_info *out_info) {
u64 offset = 12ULL;
int found_fmt = 0;
int found_data = 0;
u64 sample_rate = 0ULL;
u64 channels = 0ULL;
u64 bits = 0ULL;
u64 block_align = 0ULL;
const unsigned char *data = (const unsigned char *)0;
u64 data_size = 0ULL;
if (buffer == (const unsigned char *)0 || out_info == (ush_wav_info *)0) {
return 0;
}
if (size < 12ULL) {
return 0;
}
if (ush_wav_tag_eq(&buffer[0], "RIFF") == 0 || ush_wav_tag_eq(&buffer[8], "WAVE") == 0) {
return 0;
}
while (offset + 8ULL <= size) {
const unsigned char *chunk_tag = &buffer[offset];
u64 chunk_size = (u64)ush_wav_le32(&buffer[offset + 4ULL]);
u64 chunk_data = offset + 8ULL;
u64 next_offset;
if (chunk_data > size || chunk_size > (size - chunk_data)) {
return 0;
}
if (ush_wav_tag_eq(chunk_tag, "fmt ") != 0) {
if (chunk_size < 16ULL) {
return 0;
}
if (ush_wav_le16(&buffer[chunk_data + 0ULL]) != 1U) {
return 0;
}
channels = (u64)ush_wav_le16(&buffer[chunk_data + 2ULL]);
sample_rate = (u64)ush_wav_le32(&buffer[chunk_data + 4ULL]);
block_align = (u64)ush_wav_le16(&buffer[chunk_data + 12ULL]);
bits = (u64)ush_wav_le16(&buffer[chunk_data + 14ULL]);
found_fmt = 1;
} else if (ush_wav_tag_eq(chunk_tag, "data") != 0) {
data = &buffer[chunk_data];
data_size = chunk_size;
found_data = 1;
}
next_offset = chunk_data + chunk_size;
if ((chunk_size & 1ULL) != 0ULL) {
next_offset++;
}
if (next_offset <= offset || next_offset > size) {
break;
}
offset = next_offset;
}
if (found_fmt == 0 || found_data == 0) {
return 0;
}
if ((channels != 1ULL && channels != 2ULL) || (bits != 8ULL && bits != 16ULL)) {
return 0;
}
if (sample_rate == 0ULL || block_align == 0ULL) {
return 0;
}
if (data_size < block_align) {
return 0;
}
out_info->data = data;
out_info->data_size = data_size;
out_info->sample_rate = sample_rate;
out_info->channels = channels;
out_info->bits_per_sample = bits;
out_info->block_align = block_align;
out_info->frame_count = data_size / block_align;
return (out_info->frame_count > 0ULL) ? 1 : 0;
}
static u64 ush_wav_sample_deviation(const ush_wav_info *info, u64 frame_index) {
const unsigned char *frame;
if (info == (const ush_wav_info *)0 || info->data == (const unsigned char *)0 || info->frame_count == 0ULL) {
return 0ULL;
}
if (frame_index >= info->frame_count) {
frame_index = info->frame_count - 1ULL;
}
frame = &info->data[frame_index * info->block_align];
if (info->bits_per_sample == 8ULL) {
unsigned int left = (unsigned int)frame[0];
unsigned int dev_left = (left >= 128U) ? (left - 128U) : (128U - left);
if (info->channels == 2ULL && info->block_align >= 2ULL) {
unsigned int right = (unsigned int)frame[1];
unsigned int dev_right = (right >= 128U) ? (right - 128U) : (128U - right);
return (u64)((dev_left + dev_right) / 2U);
}
return (u64)dev_left;
}
if (info->bits_per_sample == 16ULL) {
unsigned int raw_left;
int sample_left;
unsigned int dev_left;
if (info->block_align < 2ULL) {
return 0ULL;
}
raw_left = ush_wav_le16(frame);
sample_left = (raw_left >= 32768U) ? ((int)raw_left - 65536) : (int)raw_left;
if (sample_left < 0) {
sample_left = -sample_left;
}
dev_left = (unsigned int)((unsigned int)sample_left >> 8U);
if (info->channels == 2ULL && info->block_align >= 4ULL) {
unsigned int raw_right = ush_wav_le16(frame + 2ULL);
int sample_right = (raw_right >= 32768U) ? ((int)raw_right - 65536) : (int)raw_right;
unsigned int dev_right;
if (sample_right < 0) {
sample_right = -sample_right;
}
dev_right = (unsigned int)((unsigned int)sample_right >> 8U);
return (u64)((dev_left + dev_right) / 2U);
}
return (u64)dev_left;
}
return 0ULL;
}
static int ush_wavplay_parse_args(const char *arg,
char *out_path,
u64 out_path_size,
u64 *out_steps,
u64 *out_ticks,
int *out_stop) {
char first[USH_PATH_MAX];
char second[32];
char third[32];
const char *rest = "";
const char *rest2 = "";
const char *rest3 = "";
if (out_path == (char *)0 || out_steps == (u64 *)0 || out_ticks == (u64 *)0 || out_stop == (int *)0) {
return 0;
}
*out_steps = USH_WAVPLAY_DEFAULT_STEPS;
*out_ticks = USH_WAVPLAY_DEFAULT_TICKS;
*out_stop = 0;
out_path[0] = '\0';
if (arg == (const char *)0 || arg[0] == '\0') {
return 0;
}
if (ush_split_first_and_rest(arg, first, (u64)sizeof(first), &rest) == 0) {
return 0;
}
if (ush_streq(first, "--stop") != 0 || ush_streq(first, "stop") != 0) {
if (rest != (const char *)0 && rest[0] != '\0') {
return 0;
}
*out_stop = 1;
return 1;
}
ush_copy(out_path, out_path_size, first);
if (rest != (const char *)0 && rest[0] != '\0') {
if (ush_split_first_and_rest(rest, second, (u64)sizeof(second), &rest2) == 0) {
return 0;
}
if (ush_parse_u64_dec(second, out_steps) == 0 || *out_steps == 0ULL || *out_steps > USH_WAVPLAY_MAX_STEPS) {
return 0;
}
if (rest2 != (const char *)0 && rest2[0] != '\0') {
if (ush_split_first_and_rest(rest2, third, (u64)sizeof(third), &rest3) == 0) {
return 0;
}
if (ush_parse_u64_dec(third, out_ticks) == 0 || *out_ticks == 0ULL || *out_ticks > USH_WAVPLAY_MAX_TICKS) {
return 0;
}
if (rest3 != (const char *)0 && rest3[0] != '\0') {
return 0;
}
}
}
return 1;
}
static int ush_cmd_wavplay(const ush_state *sh, const char *arg) {
char path_arg[USH_PATH_MAX];
char abs_path[USH_PATH_MAX];
ush_wav_info info;
u64 file_size;
u64 got;
u64 steps;
u64 ticks_per_step;
u64 stride;
u64 i;
u64 run_freq = 0ULL;
u64 run_ticks = 0ULL;
int stop_only;
if (sh == (const ush_state *)0) {
return 0;
}
if (ush_wavplay_parse_args(arg, path_arg, (u64)sizeof(path_arg), &steps, &ticks_per_step, &stop_only) == 0) {
ush_writeln("wavplay: usage wavplay <file.wav> [steps<=4096] [ticks<=64]");
ush_writeln("wavplay: usage wavplay --stop");
return 0;
}
if (stop_only != 0) {
(void)cleonos_sys_audio_stop();
ush_writeln("wavplay: stopped");
return 1;
}
if (cleonos_sys_audio_available() == 0ULL) {
ush_writeln("wavplay: audio device unavailable");
return 0;
}
if (ush_resolve_path(sh, path_arg, abs_path, (u64)sizeof(abs_path)) == 0) {
ush_writeln("wavplay: invalid path");
return 0;
}
if (cleonos_sys_fs_stat_type(abs_path) != 1ULL) {
ush_writeln("wavplay: file not found");
return 0;
}
file_size = cleonos_sys_fs_stat_size(abs_path);
if (file_size == (u64)-1 || file_size == 0ULL) {
ush_writeln("wavplay: empty or unreadable file");
return 0;
}
if (file_size > USH_WAVPLAY_FILE_MAX) {
ush_writeln("wavplay: file too large (max 65536 bytes)");
return 0;
}
got = cleonos_sys_fs_read(abs_path, (char *)ush_wavplay_file_buf, file_size);
if (got != file_size) {
ush_writeln("wavplay: read failed");
return 0;
}
if (ush_wav_parse(ush_wavplay_file_buf, got, &info) == 0) {
ush_writeln("wavplay: unsupported wav (need PCM 8/16-bit, mono/stereo)");
return 0;
}
if (steps > info.frame_count) {
steps = info.frame_count;
}
if (steps == 0ULL) {
ush_writeln("wavplay: nothing to play");
return 0;
}
if (steps < 8ULL) {
steps = 8ULL;
if (steps > info.frame_count) {
steps = info.frame_count;
}
}
ush_wavplay_print_meta(abs_path, &info, steps, ticks_per_step);
stride = info.frame_count / steps;
if (stride == 0ULL) {
stride = 1ULL;
}
for (i = 0ULL; i < steps; i++) {
u64 frame_index = i * stride;
u64 deviation;
u64 freq;
if (frame_index >= info.frame_count) {
frame_index = info.frame_count - 1ULL;
}
deviation = ush_wav_sample_deviation(&info, frame_index);
if (deviation < 4ULL) {
freq = 0ULL;
} else {
freq = 180ULL + (deviation * 12ULL);
}
if (run_ticks == 0ULL) {
run_freq = freq;
run_ticks = ticks_per_step;
continue;
}
if (freq == run_freq && (run_ticks + ticks_per_step) <= USH_WAVPLAY_RUN_TICK_MAX) {
run_ticks += ticks_per_step;
continue;
}
if (cleonos_sys_audio_play_tone(run_freq, run_ticks) == 0ULL) {
ush_writeln("wavplay: playback failed");
(void)cleonos_sys_audio_stop();
return 0;
}
run_freq = freq;
run_ticks = ticks_per_step;
}
if (run_ticks > 0ULL) {
if (cleonos_sys_audio_play_tone(run_freq, run_ticks) == 0ULL) {
ush_writeln("wavplay: playback failed");
(void)cleonos_sys_audio_stop();
return 0;
}
}
(void)cleonos_sys_audio_stop();
ush_writeln("wavplay: done");
return 1;
}
int cleonos_app_main(void) {
ush_cmd_ctx ctx;
ush_cmd_ret ret;
ush_state sh;
char initial_cwd[USH_PATH_MAX];
int has_context = 0;
int success = 0;
const char *arg = "";
ush_zero(&ctx, (u64)sizeof(ctx));
ush_zero(&ret, (u64)sizeof(ret));
ush_init_state(&sh);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
if (ush_command_ctx_read(&ctx) != 0) {
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "wavplay") != 0) {
has_context = 1;
arg = ctx.arg;
if (ctx.cwd[0] == '/') {
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
}
}
}
success = ush_cmd_wavplay(&sh, arg);
if (has_context != 0) {
if (ush_streq(sh.cwd, initial_cwd) == 0) {
ret.flags |= USH_CMD_RET_FLAG_CWD;
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
}
if (sh.exit_requested != 0) {
ret.flags |= USH_CMD_RET_FLAG_EXIT;
ret.exit_code = sh.exit_code;
}
(void)ush_command_ret_write(&ret);
}
return (success != 0) ? 0 : 1;
}

View File

@@ -54,6 +54,9 @@ typedef unsigned long long usize;
#define CLEONOS_SYSCALL_YIELD 45ULL
#define CLEONOS_SYSCALL_SHUTDOWN 46ULL
#define CLEONOS_SYSCALL_RESTART 47ULL
#define CLEONOS_SYSCALL_AUDIO_AVAILABLE 48ULL
#define CLEONOS_SYSCALL_AUDIO_PLAY_TONE 49ULL
#define CLEONOS_SYSCALL_AUDIO_STOP 50ULL
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
u64 cleonos_sys_log_write(const char *message, u64 length);
@@ -103,5 +106,8 @@ u64 cleonos_sys_sleep_ticks(u64 ticks);
u64 cleonos_sys_yield(void);
u64 cleonos_sys_shutdown(void);
u64 cleonos_sys_restart(void);
u64 cleonos_sys_audio_available(void);
u64 cleonos_sys_audio_play_tone(u64 hz, u64 ticks);
u64 cleonos_sys_audio_stop(void);
#endif

View File

@@ -199,3 +199,16 @@ u64 cleonos_sys_shutdown(void) {
u64 cleonos_sys_restart(void) {
return cleonos_syscall(CLEONOS_SYSCALL_RESTART, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_audio_available(void) {
return cleonos_syscall(CLEONOS_SYSCALL_AUDIO_AVAILABLE, 0ULL, 0ULL, 0ULL);
}
u64 cleonos_sys_audio_play_tone(u64 hz, u64 ticks) {
return cleonos_syscall(CLEONOS_SYSCALL_AUDIO_PLAY_TONE, hz, ticks, 0ULL);
}
u64 cleonos_sys_audio_stop(void) {
return cleonos_syscall(CLEONOS_SYSCALL_AUDIO_STOP, 0ULL, 0ULL, 0ULL);
}

View File

@@ -0,0 +1,126 @@
#include <clks/audio.h>
#include <clks/exec.h>
#include <clks/log.h>
#include <clks/types.h>
#define CLKS_AUDIO_PIT_BASE_HZ 1193182ULL
#define CLKS_AUDIO_FREQ_MIN 20ULL
#define CLKS_AUDIO_FREQ_MAX 20000ULL
#define CLKS_AUDIO_TICKS_MAX 2048ULL
static clks_bool clks_audio_ready = CLKS_FALSE;
static u64 clks_audio_played_count = 0ULL;
#if defined(CLKS_ARCH_X86_64)
static inline void clks_audio_outb(u16 port, u8 value) {
__asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port));
}
static inline u8 clks_audio_inb(u16 port) {
u8 value;
__asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
static void clks_audio_program_pc_speaker(u64 hz) {
u64 divisor64 = CLKS_AUDIO_PIT_BASE_HZ / hz;
u16 divisor;
u8 control;
if (divisor64 == 0ULL) {
divisor64 = 1ULL;
}
if (divisor64 > 0xFFFFULL) {
divisor64 = 0xFFFFULL;
}
divisor = (u16)divisor64;
clks_audio_outb(0x43U, 0xB6U);
clks_audio_outb(0x42U, (u8)(divisor & 0xFFU));
clks_audio_outb(0x42U, (u8)((divisor >> 8) & 0xFFU));
control = clks_audio_inb(0x61U);
clks_audio_outb(0x61U, (u8)(control | 0x03U));
}
#endif
static u64 clks_audio_clamp_hz(u64 hz) {
if (hz < CLKS_AUDIO_FREQ_MIN) {
return CLKS_AUDIO_FREQ_MIN;
}
if (hz > CLKS_AUDIO_FREQ_MAX) {
return CLKS_AUDIO_FREQ_MAX;
}
return hz;
}
void clks_audio_init(void) {
#if defined(CLKS_ARCH_X86_64)
clks_audio_ready = CLKS_TRUE;
clks_audio_played_count = 0ULL;
clks_audio_stop();
clks_log(CLKS_LOG_INFO, "AUDIO", "PC SPEAKER ONLINE");
clks_log_hex(CLKS_LOG_INFO, "AUDIO", "PIT_BASE_HZ", CLKS_AUDIO_PIT_BASE_HZ);
#else
clks_audio_ready = CLKS_FALSE;
clks_audio_played_count = 0ULL;
clks_log(CLKS_LOG_WARN, "AUDIO", "AUDIO OUTPUT NOT AVAILABLE ON THIS ARCH");
#endif
}
clks_bool clks_audio_available(void) {
return clks_audio_ready;
}
clks_bool clks_audio_play_tone(u64 hz, u64 ticks) {
if (clks_audio_ready == CLKS_FALSE) {
return CLKS_FALSE;
}
if (ticks == 0ULL) {
return CLKS_TRUE;
}
if (ticks > CLKS_AUDIO_TICKS_MAX) {
ticks = CLKS_AUDIO_TICKS_MAX;
}
if (hz == 0ULL) {
clks_audio_stop();
(void)clks_exec_sleep_ticks(ticks);
return CLKS_TRUE;
}
hz = clks_audio_clamp_hz(hz);
#if defined(CLKS_ARCH_X86_64)
clks_audio_program_pc_speaker(hz);
(void)clks_exec_sleep_ticks(ticks);
clks_audio_stop();
clks_audio_played_count++;
return CLKS_TRUE;
#else
return CLKS_FALSE;
#endif
}
void clks_audio_stop(void) {
#if defined(CLKS_ARCH_X86_64)
u8 control;
if (clks_audio_ready == CLKS_FALSE) {
return;
}
control = clks_audio_inb(0x61U);
clks_audio_outb(0x61U, (u8)(control & 0xFCU));
#endif
}
u64 clks_audio_play_count(void) {
return clks_audio_played_count;
}

12
clks/include/clks/audio.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef CLKS_AUDIO_H
#define CLKS_AUDIO_H
#include <clks/types.h>
void clks_audio_init(void);
clks_bool clks_audio_available(void);
clks_bool clks_audio_play_tone(u64 hz, u64 ticks);
void clks_audio_stop(void);
u64 clks_audio_play_count(void);
#endif

View File

@@ -10,6 +10,7 @@ enum clks_driver_kind {
CLKS_DRIVER_KIND_BUILTIN_VIDEO = 2,
CLKS_DRIVER_KIND_BUILTIN_TTY = 3,
CLKS_DRIVER_KIND_ELF = 4,
CLKS_DRIVER_KIND_BUILTIN_AUDIO = 5,
};
enum clks_driver_state {

View File

@@ -51,6 +51,9 @@
#define CLKS_SYSCALL_YIELD 45ULL
#define CLKS_SYSCALL_SHUTDOWN 46ULL
#define CLKS_SYSCALL_RESTART 47ULL
#define CLKS_SYSCALL_AUDIO_AVAILABLE 48ULL
#define CLKS_SYSCALL_AUDIO_PLAY_TONE 49ULL
#define CLKS_SYSCALL_AUDIO_STOP 50ULL
void clks_syscall_init(void);
u64 clks_syscall_dispatch(void *frame_ptr);

View File

@@ -1,4 +1,5 @@
#include <clks/driver.h>
#include <clks/audio.h>
#include <clks/elf64.h>
#include <clks/framebuffer.h>
#include <clks/fs.h>
@@ -115,6 +116,12 @@ static void clks_driver_register_builtins(void) {
clks_driver_push("framebuffer", CLKS_DRIVER_KIND_BUILTIN_VIDEO, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
clks_driver_push("tty", CLKS_DRIVER_KIND_BUILTIN_TTY, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
}
if (clks_audio_available() == CLKS_TRUE) {
clks_driver_push("pcspeaker", CLKS_DRIVER_KIND_BUILTIN_AUDIO, CLKS_DRIVER_STATE_READY, CLKS_FALSE, 0ULL, 0ULL);
} else {
clks_driver_push("pcspeaker", CLKS_DRIVER_KIND_BUILTIN_AUDIO, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
}
}
static void clks_driver_probe_driver_dir(void) {

View File

@@ -1,6 +1,7 @@
// Kernel main function
#include <clks/boot.h>
#include <clks/audio.h>
#include <clks/cpu.h>
#include <clks/desktop.h>
#include <clks/driver.h>
@@ -175,6 +176,7 @@ void clks_kernel_main(void) {
}
clks_exec_init();
clks_audio_init();
clks_keyboard_init();
clks_mouse_init();
clks_desktop_init();

View File

@@ -1,4 +1,5 @@
#include <clks/cpu.h>
#include <clks/audio.h>
#include <clks/exec.h>
#include <clks/fs.h>
#include <clks/heap.h>
@@ -280,6 +281,22 @@ static u64 clks_syscall_restart(void) {
}
static u64 clks_syscall_audio_available(void) {
return (clks_audio_available() == CLKS_TRUE) ? 1ULL : 0ULL;
}
static u64 clks_syscall_audio_play_tone(u64 arg0, u64 arg1) {
if (clks_audio_play_tone(arg0, arg1) == CLKS_FALSE) {
return 0ULL;
}
return 1ULL;
}
static u64 clks_syscall_audio_stop(void) {
clks_audio_stop();
return 1ULL;
}
static u64 clks_syscall_fs_stat_type(u64 arg0) {
char path[CLKS_SYSCALL_PATH_MAX];
struct clks_fs_node_info info;
@@ -582,6 +599,12 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
return clks_syscall_shutdown();
case CLKS_SYSCALL_RESTART:
return clks_syscall_restart();
case CLKS_SYSCALL_AUDIO_AVAILABLE:
return clks_syscall_audio_available();
case CLKS_SYSCALL_AUDIO_PLAY_TONE:
return clks_syscall_audio_play_tone(frame->rbx, frame->rcx);
case CLKS_SYSCALL_AUDIO_STOP:
return clks_syscall_audio_stop();
default:
return (u64)-1;
}

View File

@@ -52,7 +52,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `FS_MKDIR` / `FS_WRITE` / `FS_APPEND` / `FS_REMOVE` 仅允许 `/temp` 树下路径。
## 4. Syscall 列表0~47
## 4. Syscall 列表0~50
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
@@ -350,6 +350,27 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- 返回:理论上不返回;成功路径会触发重启流程(当前 x86_64 走 8042 reset
- 说明:若重启流程未生效,内核会进入 halt 循环。
### 48 `CLEONOS_SYSCALL_AUDIO_AVAILABLE`
- 参数:无
- 返回:
- `1`:音频输出可用
- `0`:当前平台无音频输出
### 49 `CLEONOS_SYSCALL_AUDIO_PLAY_TONE`
- 参数:
- `arg0`: `u64 hz`(频率,`0` 表示静音等待)
- `arg1`: `u64 ticks`(持续 tick
- 返回:成功 `1`,失败 `0`
- 说明:当前实现基于 PC Speakerx86_64用于最小音频链路。
### 50 `CLEONOS_SYSCALL_AUDIO_STOP`
- 参数:无
- 返回:当前实现固定返回 `1`
- 说明:立即停止当前音频输出。
## 5. 用户态封装函数
用户态封装位于:
@@ -366,6 +387,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
- `cleonos_sys_kbd_get_char()` / `cleonos_sys_kbd_buffered()`
- `cleonos_sys_getpid()` / `cleonos_sys_spawn_path()` / `cleonos_sys_wait_pid()`
- `cleonos_sys_exit()` / `cleonos_sys_sleep_ticks()` / `cleonos_sys_yield()` / `cleonos_sys_shutdown()` / `cleonos_sys_restart()`
- `cleonos_sys_audio_available()` / `cleonos_sys_audio_play_tone()` / `cleonos_sys_audio_stop()`
## 6. 开发注意事项

BIN
ramdisk/test.wav Normal file

Binary file not shown.