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

@@ -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;
}