NJU-ProjectN / ics-pa-gitbook

554 stars 152 forks source link

[Suggestions] 在 am_native 中增加允许声卡多次打开的代码,并在 pa3、pa4 中完善声卡相关的提示 #24

Closed rijuyuezhu closed 7 months ago

rijuyuezhu commented 1 year ago

在 PA 中出现的所有设备中,声卡应该是最特殊的一种:它在打开时会持续地“记录” freq, channels, samples 三个参数,且在之后不会更改。当机器上自始至终仅运行一个程序时,这不会出现问题。但是在 pa3 中,若 /bin/nterm 存在音乐并进入其它程序(如 pal),或若在程序 exit 后重新进入 /bin/nterm 并打开新的程序。在这种情况下,声卡会被打开多次。若两次参数 freq 等存在差异,则可能会导致音频播放出现异常。故建议在 am_native 上添加允许声卡多次打开的代码,并在讲义中加入在 nemu 的声卡部分进行调整,允许其多次打开的提示。以下是我的修改:

--- a/abstract-machine/am/src/native/ioe/audio.c
+++ b/abstract-machine/am/src/native/ioe/audio.c
@@ -6,6 +6,7 @@

 static int rfd = -1, wfd = -1;
 static volatile int count = 0;
+static int audio_on;

 void __am_audio_init() {
   int fds[2];
@@ -41,6 +42,13 @@ static void audio_write(uint8_t *buf, int len) {
 }

 void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) {
+  if (audio_on) {
+    SDL_CloseAudio();
+
+    // clean the pipe
+    static uint8_t buf[4096];
+    while (read(rfd, buf, 4096) > 0) ;
+  }
   SDL_AudioSpec s = {};
   s.freq = ctrl->freq;
   s.format = AUDIO_S16SYS;
@@ -52,6 +60,7 @@ void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) {
   count = 0;
   int ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
   if (ret == 0) {
+    audio_on = 1;
     SDL_OpenAudio(&s, NULL);
     SDL_PauseAudio(0);
   }

其中管道的清空是必要的,否则可能出现阻塞。但我这里使用的方案个人认为并不优雅,不知道有没有更好的方法。

在 pa4 中,涉及到多个程序的切换(主要是最后的 F1, F2, F3 演示。让两个程序分时运行同时使用声卡应是不允许的,正如不能让两个程序朴素地同时使用 vga)。此时个人认为应该由 OS 进行声卡的切换管理,比如可以在 pcb 中加入相关参数。同样建议在 pa4 讲义中加入相关提示。

Suggestions:

  1. (important) Let the am native support the reopen of sound card.
  2. (not quite important) Add prompt in the teaching materials, as mentioned above. I think this is not quite important because the cause of this problem is not obscure and those who are willing to complete the audio part are strong enough to solve this problem on their own.
sashimi-yzh commented 1 year ago

一般是播放音频的时候对音频数据进行转码, 例如, 默认以44100Hz双声道初始化音频设备之后, 如果需要播放的音频属性不同, 则对音频数据进行"扩展"或"截断", 然后再交给设备层播放.

PA4最后的选做部分有一些简单的介绍.