소스 검색

Use average of both output ports to determine audio level.

This appears to match the behavior expected from old drives, even though it does not appear within the specifications.
saybur 2 년 전
부모
커밋
dfbed1ec63
3개의 변경된 파일24개의 추가작업 그리고 20개의 파일을 삭제
  1. 5 4
      lib/BlueSCSI_platform_RP2040/audio.cpp
  2. 12 7
      src/BlueSCSI_audio.h
  3. 7 9
      src/BlueSCSI_mode.cpp

+ 5 - 4
lib/BlueSCSI_platform_RP2040/audio.cpp

@@ -141,7 +141,7 @@ static uint32_t fleft;
 static audio_status_code audio_last_status[8] = {ASC_NO_STATUS};
 
 // volume information for targets
-static volatile uint8_t volumes[8] = {
+static volatile uint16_t volumes[8] = {
     DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL,
     DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL
 };
@@ -164,7 +164,8 @@ static uint8_t invert = 0; // biphase encode help: set if last wire bit was '1'
  * output.
  */
 static void snd_encode(uint8_t* samples, uint16_t* wire_patterns, uint16_t len, uint8_t swap) {
-    uint8_t vol = volumes[audio_owner & 7];
+    uint16_t wvol = volumes[audio_owner & 7];
+    uint8_t vol = ((wvol >> 8) + (wvol & 0xFF)) >> 1; // average of both values
     // limit maximum volume; with my DACs I've had persistent issues
     // with signal clipping when sending data in the highest bit position
     vol = vol >> 2;
@@ -553,11 +554,11 @@ audio_status_code audio_get_status_code(uint8_t id) {
     return tmp;
 }
 
-uint8_t audio_get_volume(uint8_t id) {
+uint16_t audio_get_volume(uint8_t id) {
     return volumes[id & 7];
 }
 
-void audio_set_volume(uint8_t id, uint8_t vol) {
+void audio_set_volume(uint8_t id, uint16_t vol) {
     volumes[id & 7] = vol;
 }
 

+ 12 - 7
src/BlueSCSI_audio.h

@@ -29,8 +29,11 @@
  * max volume. SCSI-2 says this should be 25% of maximum by default, MMC-1
  * says 100%. Testing shows this tends to be obnoxious at high volumes, so
  * go with SCSI-2.
+ *
+ * This implementation uses the high byte for output port 1 and the low byte
+ * for port 0. The two values are averaged to determine final volume level.
  */
-#define DEFAULT_VOLUME_LEVEL 63
+#define DEFAULT_VOLUME_LEVEL 0x3F3F
 
 /*
  * Status codes for audio playback, matching the SCSI 'audio status codes'.
@@ -96,19 +99,21 @@ void audio_stop(uint8_t id);
 audio_status_code audio_get_status_code(uint8_t id);
 
 /**
- * Gets the current volume level for a target. This is a range from 0-255,
- * with 0 being muted and 255 being max volume. See 0x0E mode page for more.
+ * Gets the current volume level for a target. This is a pair of 8-bit values
+ * ranging from 0-255 that are averaged together to determine the final output
+ * level, where 0 is muted and 255 is maximum volume. The high byte corresponds
+ * to 0x0E channel 1 and the low byte to 0x0E channel 0. See the spec's mode
+ * page documentation for more details.
  *
  * \param id    SCSI ID to provide volume for.
  * \return      The matching volume level.
  */
-uint8_t audio_get_volume(uint8_t id);
+uint16_t audio_get_volume(uint8_t id);
 
 /**
- * Sets the volume level for a target. This is a range from 0-255, with 0
- * being muted and 255 being max volume. See 0x0E mode page for more.
+ * Sets the volume level for a target, as above. See 0x0E mode page for more.
  *
  * \param id    SCSI ID to set volume for.
  * \param vol   The new volume level.
  */
-void audio_set_volume(uint8_t id, uint8_t vol);
+void audio_set_volume(uint8_t id, uint16_t vol);

+ 7 - 9
src/BlueSCSI_mode.cpp

@@ -108,8 +108,9 @@ int modeSenseCDAudioControlPage(int pc, int idx, int pageCode, int* pageFound)
         if (pc == 0x00)
         {
             // report current volume level
-            scsiDev.data[idx+9] = audio_get_volume(scsiDev.target->targetId);
-            scsiDev.data[idx+11] = audio_get_volume(scsiDev.target->targetId);
+            uint16_t vol = audio_get_volume(scsiDev.target->targetId);
+            scsiDev.data[idx+9] = vol & 0xFF;
+            scsiDev.data[idx+11] = vol >> 8;
         }
         else if (pc == 0x01)
         {
@@ -122,8 +123,8 @@ int modeSenseCDAudioControlPage(int pc, int idx, int pageCode, int* pageFound)
             // report defaults for 0x02
             // also report same for 0x03, though we are actually supposed
             // to terminate with CHECK CONDITION and SAVING PARAMETERS NOT SUPPORTED
-            scsiDev.data[idx+9] = DEFAULT_VOLUME_LEVEL;
-            scsiDev.data[idx+11] = DEFAULT_VOLUME_LEVEL;
+            scsiDev.data[idx+9] = DEFAULT_VOLUME_LEVEL & 0xFF;
+            scsiDev.data[idx+11] = DEFAULT_VOLUME_LEVEL >> 8;
         }
         return sizeof(CDROMAudioControlParametersPage);
     }
@@ -143,11 +144,8 @@ int modeSelectCDAudioControlPage(int pageLen, int idx)
     if (scsiDev.target->cfg->deviceType == S2S_CFG_OPTICAL)
     {
         if (pageLen != 0x0E) return 0;
-        uint8_t volL = scsiDev.data[idx+9];
-        uint8_t volR = scsiDev.data[idx+11];
-        // only support setting channels to same volume, just pick higher
-        uint8_t vol = (volL > volR) ? volL : volR;
-        debuglog("------ CD audio control page volume (", volL, ",", volR, ")");
+        uint16_t vol = (scsiDev.data[idx+11] << 8) + scsiDev.data[idx+9];
+        debuglog("------ CD audio control page volume (", vol, ")");
         audio_set_volume(scsiDev.target->targetId, vol);
         return 1;
     }