Change default sample rate to 48kHz and add validation
Changes: - Update default sample rate from 44.1kHz to 48kHz (more professional standard) - Add sample rate validation in play_sound_file() - Display clear warning when uploaded file doesn't match configured rate - Update default sound generation (dial tone & beep) to use configured RATE - Prevent playback of incompatible sample rates (avoids ALSA errors) Error Handling: - Check file sample rate before attempting playback - Print warning with actual vs expected sample rate - Return False and skip playback if mismatch detected - User-friendly error message with resampling instructions This fixes the "Invalid sample rate" error when playing files with non-matching sample rates. Users must now resample their audio files to match the configured rate (default 48kHz). To resample audio files: ffmpeg -i input.wav -ar 48000 output.wav 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
"chunk_size": 1024,
|
||||
"format": "paInt16",
|
||||
"channels": 1,
|
||||
"sample_rate": 44100,
|
||||
"sample_rate": 48000,
|
||||
"max_record_seconds": 300
|
||||
},
|
||||
"paths": {
|
||||
|
||||
@@ -354,35 +354,33 @@ class RotaryPhone:
|
||||
|
||||
def generate_default_dialtone(self):
|
||||
"""Generate a classic dial tone (350Hz + 440Hz) and save as default"""
|
||||
print("Generating default dial tone...")
|
||||
print(f"Generating default dial tone at {RATE}Hz...")
|
||||
duration = 3
|
||||
sample_rate = 44100
|
||||
t = np.linspace(0, duration, int(sample_rate * duration), False)
|
||||
|
||||
t = np.linspace(0, duration, int(RATE * duration), False)
|
||||
|
||||
# Generate two frequencies and combine them
|
||||
tone1 = np.sin(2 * np.pi * 350 * t)
|
||||
tone2 = np.sin(2 * np.pi * 440 * t)
|
||||
tone = (tone1 + tone2) / 2
|
||||
|
||||
|
||||
# Convert to 16-bit PCM
|
||||
tone = (tone * 32767).astype(np.int16)
|
||||
|
||||
|
||||
# Save as WAV file
|
||||
wf = wave.open(DIALTONE_FILE, 'wb')
|
||||
wf.setnchannels(1)
|
||||
wf.setsampwidth(2) # 16-bit
|
||||
wf.setframerate(sample_rate)
|
||||
wf.setframerate(RATE)
|
||||
wf.writeframes(tone.tobytes())
|
||||
wf.close()
|
||||
print(f"Default dial tone saved to {DIALTONE_FILE}")
|
||||
print(f"Default dial tone saved to {DIALTONE_FILE} ({RATE}Hz, 16-bit)")
|
||||
|
||||
def generate_default_beep(self):
|
||||
"""Generate a simple beep tone (1000Hz) to indicate recording start"""
|
||||
print("Generating default beep sound...")
|
||||
print(f"Generating default beep sound at {RATE}Hz...")
|
||||
beep_file = os.path.join(SOUNDS_DIR, "beep.wav")
|
||||
duration = 0.5 # Half second beep
|
||||
sample_rate = 44100
|
||||
t = np.linspace(0, duration, int(sample_rate * duration), False)
|
||||
t = np.linspace(0, duration, int(RATE * duration), False)
|
||||
|
||||
# Generate 1000Hz tone
|
||||
frequency = 1000
|
||||
@@ -395,10 +393,10 @@ class RotaryPhone:
|
||||
wf = wave.open(beep_file, 'wb')
|
||||
wf.setnchannels(1)
|
||||
wf.setsampwidth(2) # 16-bit
|
||||
wf.setframerate(sample_rate)
|
||||
wf.setframerate(RATE)
|
||||
wf.writeframes(tone.tobytes())
|
||||
wf.close()
|
||||
print(f"Default beep sound saved to {beep_file}")
|
||||
print(f"Default beep sound saved to {beep_file} ({RATE}Hz, 16-bit)")
|
||||
|
||||
def play_sound_file(self, filepath, check_hook_status=True):
|
||||
"""Play a WAV file with volume control
|
||||
@@ -417,11 +415,19 @@ class RotaryPhone:
|
||||
try:
|
||||
wf = wave.open(filepath, 'rb')
|
||||
|
||||
# Check sample rate compatibility
|
||||
file_rate = wf.getframerate()
|
||||
if file_rate != RATE:
|
||||
print(f"WARNING: File sample rate ({file_rate}Hz) doesn't match configured rate ({RATE}Hz)")
|
||||
print(f"Audio may not play correctly. Please resample the file to {RATE}Hz")
|
||||
wf.close()
|
||||
return False
|
||||
|
||||
# Use configured audio device
|
||||
stream = self.audio.open(
|
||||
format=self.audio.get_format_from_width(wf.getsampwidth()),
|
||||
channels=wf.getnchannels(),
|
||||
rate=wf.getframerate(),
|
||||
rate=file_rate,
|
||||
output=True,
|
||||
output_device_index=AUDIO_DEVICE_INDEX,
|
||||
frames_per_buffer=CHUNK
|
||||
|
||||
Reference in New Issue
Block a user