Skip to content

Commit f5d381b

Browse files
ac97 44.1khz raw shenanigans
1 parent f1f1ca4 commit f5d381b

File tree

2 files changed

+19
-66
lines changed

2 files changed

+19
-66
lines changed

modules/ac97/ac97.c

Lines changed: 19 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ static inline void delay_us(unsigned us) {
1919
}
2020
}
2121

22+
2223
static bool ac97_reset_and_unmute(void) {
2324
/* Exit cold reset (run): set bit1 in GLOB_CNT. */
2425
outl(g.nabm + AC97_NABM_GLOB_CNT, 0x00000002);
@@ -35,7 +36,8 @@ static bool ac97_reset_and_unmute(void) {
3536
if (caps & 0x0001) {
3637
uint16_t ec = inw(g.nam + AC97_NAM_EXT_CTRL);
3738
outw(g.nam + AC97_NAM_EXT_CTRL, ec | 0x0001);
38-
outw(g.nam + AC97_NAM_PCM_FRONT_RATE, 48000);
39+
outw(g.nam + AC97_NAM_PCM_FRONT_RATE, 44100);
40+
dprintf("ac97: PCM front DAC rate now %u Hz\n", inw(g.nam + AC97_NAM_PCM_FRONT_RATE));
3941
}
4042
return true;
4143
}
@@ -93,7 +95,7 @@ static bool init_ac97(void) {
9395
}
9496
if (ac97_start(dev)) {
9597
kprintf("ac97: started\n");
96-
ac97_stream_prepare(4096 /*frag bytes*/, 48000 /*Hz*/);
98+
ac97_stream_prepare(4096, 44100); // 44.1khz stereo LE 16 bit
9799
} else {
98100
dprintf("ac97: start failed\n");
99101
return false;
@@ -318,8 +320,6 @@ void ac97_idle(void) {
318320
if (s_q_head_fr == s_q_len_fr) {
319321
s_q_head_fr = 0;
320322
s_q_len_fr = 0;
321-
/* (buffer kept for reuse; free here if you want to release memory when idle) */
322-
/* if (s_q_cap_fr > SOME_LIMIT) { kfree(s_q_pcm); s_q_pcm=NULL; s_q_cap_fr=0; } */
323323
}
324324

325325
/* recover from a halted engine if needed (cheap check) */
@@ -330,78 +330,31 @@ void ac97_idle(void) {
330330
}
331331
}
332332

333-
334-
void ac97_test_melody(void) {
335-
if (!g.bdl || !g.buf || g.bdl_n != 32 || g.frag_frames == 0 || g.frag_bytes == 0) {
336-
dprintf("ac97: test_melody: stream not prepared\n");
337-
return;
338-
}
339-
340-
/* One ephemeral staging fragment (stereo S16LE). No special alignment needed. */
341-
int16_t *frag = kmalloc(g.frag_bytes);
342-
if (!frag) {
343-
dprintf("ac97: test_melody: OOM\n");
344-
return;
345-
}
346-
347-
/* Use actual programmed rate if var-rate is enabled; otherwise assume 48k. */
333+
uint32_t ac97_get_hz() {
348334
uint32_t rate = 48000;
349335
uint16_t caps = inw(g.nam + AC97_NAM_EXT_CAPS);
350336
if (caps & 0x0001) {
351337
if (inw(g.nam + AC97_NAM_EXT_CTRL) & 0x0001) {
352338
rate = inw(g.nam + AC97_NAM_PCM_FRONT_RATE);
353-
if (rate == 0) rate = 48000;
354-
}
355-
}
356-
357-
/* Little square-wave line: A4 B4 C5 E5 D5 C5 B4 A4 A5 (each ~60 ms) */
358-
static const uint16_t notes_hz[] = {440, 494, 523, 659, 587, 523, 494, 440, 880};
359-
static const uint16_t dur_ms[] = {600, 600, 600, 600, 600, 600, 600, 600, 600};
360-
const size_t nnotes = sizeof(notes_hz) / sizeof(notes_hz[0]);
361-
362-
const uint32_t F = g.frag_frames; /* frames per fragment (stereo S16) */
363-
size_t total_frames_enqueued = 0;
364-
365-
for (size_t n = 0; n < nnotes; n++) {
366-
const uint32_t freq = notes_hz[n];
367-
uint32_t frames_left = (rate / 1000u) * dur_ms[n];
368-
if (freq == 0) continue;
369-
370-
/* Integer square-wave state */
371-
uint32_t period = rate / freq;
372-
if (period == 0) period = 1;
373-
uint32_t halfperiod = period >> 1;
374-
uint32_t phase = 0;
375-
376-
while (frames_left > 0) {
377-
const uint32_t out_frames = (frames_left > F) ? F : frames_left;
378-
379-
/* Generate exactly out_frames into the staging fragment */
380-
for (uint32_t i = 0; i < out_frames; i++) {
381-
const int16_t s = (phase < halfperiod) ? 6000 : (int16_t) -6000;
382-
frag[(i << 1)] = s; /* L */
383-
frag[(i << 1) + 1] = s; /* R */
384-
if (++phase >= period) phase = 0;
385-
}
386-
387-
/* Non-blocking enqueue (zero-pads the tail of the fragment inside ac97_play_s16le) */
388-
const size_t pushed = push_all_s16le(frag, out_frames);
389-
if (pushed == 0 || pushed < out_frames) {
390-
dprintf("ac97: test_melody: ring full after %zu frames\n", total_frames_enqueued);
391-
kfree(frag);
392-
return;
339+
if (rate == 0) {
340+
rate = 48000;
393341
}
394-
395-
total_frames_enqueued += pushed;
396-
frames_left -= out_frames;
397342
}
398343
}
344+
return rate;
345+
}
399346

400-
dprintf("ac97: test_melody: enqueued %zu frames (~%u ms)\n",
401-
total_frames_enqueued,
402-
(unsigned) ((total_frames_enqueued * 1000u) / rate));
347+
void ac97_test_melody(void) {
348+
if (!g.bdl || !g.buf || g.bdl_n != 32 || g.frag_frames == 0 || g.frag_bytes == 0) {
349+
dprintf("ac97: test_melody: stream not prepared\n");
350+
return;
351+
}
403352

404-
kfree(frag); /* safe: hardware reads from the DMA ring, not this staging buffer */
353+
fs_directory_entry_t* entry = fs_get_file_info("/system/webserver/test.raw");
354+
int16_t* data = kmalloc(entry->size);
355+
fs_read_file(entry, 0, entry->size, (unsigned char*)data);
356+
push_all_s16le(data, entry->size / sizeof(int16_t) / 2);
357+
kfree(data);
405358
}
406359

407360
/* ===================== Module entry points ===================== */

os/system/webserver/test.raw

2.01 MB
Binary file not shown.

0 commit comments

Comments
 (0)