diff --git a/examples/easy_wav_player.py b/examples/easy_wav_player.py index 6053da1..3b31ad7 100644 --- a/examples/easy_wav_player.py +++ b/examples/easy_wav_player.py @@ -56,7 +56,7 @@ elif os.uname().machine.count("Raspberry"): from sdcard import SDCard - from machine import SPI + from machine import SPI, ADC cs = Pin(13, machine.Pin.OUT) spi = SPI( @@ -84,6 +84,10 @@ I2S_ID = 0 BUFFER_LENGTH_IN_BYTES = 40000 # ======= I2S CONFIGURATION ======= + + # ======= ADC CONFIGURATION ======= + adc = ADC(0) # ADC0 corresponds to GPIO26 on Raspberry Pi Pico + # ======= ADC CONFIGURATION ======= elif os.uname().machine.count("MIMXRT"): from machine import SDCard @@ -116,10 +120,14 @@ # wait until the entire WAV file has been played while wp.isplaying() == True: # other actions can be done inside this loop during playback + adc_value = adc.read_u16() # Read 16-bit ADC value (0-65535) + volume = adc_value / 65535 # Normalize to 0.0 - 1.0 + wp.set_volume(volume) + time.sleep(0.05) pass wp.play("music-16k-16bits-mono.wav", loop=False) time.sleep(10) # play for 10 seconds wp.pause() time.sleep(5) # pause playback for 5 seconds -wp.resume() # continue playing to the end of the WAV file +wp.resume() # continue playing to the end of the WAV file \ No newline at end of file diff --git a/examples/wavplayer.py b/examples/wavplayer.py index 68dd698..660f7f6 100644 --- a/examples/wavplayer.py +++ b/examples/wavplayer.py @@ -56,6 +56,46 @@ def __init__(self, id, sck_pin, ws_pin, sd_pin, ibuf, root="/sd"): # allocate audio sample array buffer self.wav_samples_mv = memoryview(bytearray(10000)) + # Initialize volume control variable (0.0 to 1.0) + self.volume = 1.0 + self.volume_int = 256 # 256 corresponds to 1.0 in fixed-point representation + + def set_volume(self, volume): + if 0 <= volume <= 1: + self.volume = volume + self.volume_int = int(volume * 256) # Scale to 0-256 + else: + raise ValueError("Volume must be between 0.0 and 1.0") + + @micropython.viper + def adjust_volume_16bit(self, data_in: ptr8, length: int, volume_int: int): + data = ptr8(data_in) + n = int(length // 2) + for i in range(n): + # Read two bytes and combine them into a signed 16-bit integer + low = int(data[2 * i]) + high = int(data[2 * i + 1]) + sample = (high << 8) | low + if sample >= 32768: + sample -= 65536 # Convert to signed int16 + + # Adjust volume + sample = (sample * volume_int) >> 8 + + # Clip to int16 range + if sample > 32767: + sample = 32767 + elif sample < -32768: + sample = -32768 + + # Convert back to unsigned int16 + if sample < 0: + sample += 65536 + + # Store back into data buffer + data[2 * i] = sample & 0xFF + data[2 * i + 1] = (sample >> 8) & 0xFF + def i2s_callback(self, arg): if self.state == WavPlayer.PLAY: self.num_read = self.wav.readinto(self.wav_samples_mv) @@ -69,6 +109,10 @@ def i2s_callback(self, arg): _ = self.wav.seek(self.first_sample_offset) _ = self.audio_out.write(self.silence_samples) else: + # Adjust volume + if self.bits_per_sample == 16: + volume_int = self.volume_int # Integer between 0 and 256 + self.adjust_volume_16bit(self.wav_samples_mv, self.num_read, volume_int) _ = self.audio_out.write(self.wav_samples_mv[: self.num_read]) elif self.state == WavPlayer.RESUME: self.state = WavPlayer.PLAY @@ -181,4 +225,4 @@ def isplaying(self): if self.state != WavPlayer.STOP: return True else: - return False + return False \ No newline at end of file