Skip to content

Commit c153bbe

Browse files
AudioPlayer: fix volume scaling
1 parent 4afcd04 commit c153bbe

File tree

1 file changed

+26
-12
lines changed
  • internal_filesystem/apps/com.micropythonos.musicplayer/assets

1 file changed

+26
-12
lines changed

internal_filesystem/apps/com.micropythonos.musicplayer/assets/audio_player.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import machine
22
import os
33
import time
4+
import micropython
5+
46

57
# ----------------------------------------------------------------------
68
# AudioPlayer – robust, volume-controllable WAV player
79
# ----------------------------------------------------------------------
810
class AudioPlayer:
911
# class-level defaults (shared by every instance)
1012
_i2s = None # the I2S object (created once per playback)
11-
_volume = 100 # 0-100 (100 = full scale)
13+
_volume = 50 # 0-100 (100 = full scale)
1214

1315
@staticmethod
1416
def find_data_chunk(f):
@@ -102,25 +104,37 @@ def play_wav(cls, filename):
102104
print(f"Playing {data_size} bytes (vol {cls._volume}%) …")
103105
f.seek(data_start)
104106

107+
@micropython.viper
108+
def scale_audio(buf: ptr8, num_bytes: int, scale_fixed: int):
109+
for i in range(0, num_bytes, 2):
110+
lo = int(buf[i])
111+
hi = int(buf[i+1])
112+
sample = (hi << 8) | lo
113+
if hi & 128:
114+
sample -= 65536
115+
sample = (sample * scale_fixed) // 32768
116+
if sample > 32767:
117+
sample = 32767
118+
elif sample < -32768:
119+
sample = -32768
120+
buf[i] = sample & 255
121+
buf[i+1] = (sample >> 8) & 255
122+
105123
chunk_size = 4096 # 4 KB → safe on ESP32
106124

107125
total = 0
108126
while total < data_size:
109127
to_read = min(chunk_size, data_size - total)
110-
raw = f.read(to_read)
128+
raw = bytearray(f.read(to_read)) # mutable for in-place scaling
111129
if not raw:
112130
break
113131

114-
# ---- on-the-fly volume scaling (16-bit little-endian) ----
115-
scale = cls._volume / 100.0 # float 0.0-1.0
116-
if scale < 0.9:
117-
scaled = bytearray(len(raw))
118-
for i in range(0, len(raw), 2):
119-
sample = int.from_bytes(raw[i:i+2], 'little', True)
120-
sample = int(sample * scale)
121-
scaled[i:i+2] = sample.to_bytes(2, 'little', True)
122-
raw = bytes(scaled)
123-
# ---------------------------------------------------------
132+
# ---- fast viper scaling (in-place) ----
133+
scale = cls._volume / 100.0 # adjust the volume on the fly instead of at the start of playback
134+
if scale < 1.0:
135+
scale_fixed = int(scale * 32768)
136+
scale_audio(raw, len(raw), scale_fixed)
137+
# ---------------------------------------
124138

125139
if cls._i2s:
126140
cls._i2s.write(raw)

0 commit comments

Comments
 (0)