#!/usr/bin/env python3 """ Complete HiFiBerry Test - Verify speaker and microphone work """ import pyaudio import wave import numpy as np import time import os import json import sys # Load configuration def load_config(): """Load audio device configuration""" config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.json') if not os.path.exists(config_path): print("Config file not found. Using default device index 1") return {"audio": {"device_index": 1, "sample_rate": 44100}} try: with open(config_path, 'r') as f: return json.load(f) except: print("Error reading config. Using defaults.") return {"audio": {"device_index": 1, "sample_rate": 44100}} CONFIG = load_config() HIFIBERRY_INDEX = CONFIG['audio']['device_index'] SAMPLE_RATE = CONFIG['audio']['sample_rate'] def test_playback(): """Test speaker output""" print("\n" + "="*60) print("šŸ”Š TESTING SPEAKER PLAYBACK") print("="*60) audio = pyaudio.PyAudio() try: # Show device info info = audio.get_device_info_by_index(HIFIBERRY_INDEX) print(f"\nUsing device: {info['name']}") print(f"Max output channels: {info['maxOutputChannels']}") # Generate test tone (440Hz A note) print("\nGenerating 440Hz test tone...") duration = 3 t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False) tone = np.sin(2 * np.pi * 440 * t) tone = (tone * 0.3 * 32767).astype(np.int16) # 30% volume # Open stream stream = audio.open( format=pyaudio.paInt16, channels=1, rate=SAMPLE_RATE, output=True, output_device_index=HIFIBERRY_INDEX, frames_per_buffer=1024 ) print("šŸŽµ Playing 3-second tone - LISTEN NOW!") print(" You should hear a clear beep from your speaker...") # Play chunk_size = 2048 for i in range(0, len(tone.tobytes()), chunk_size): stream.write(tone.tobytes()[i:i + chunk_size]) stream.stop_stream() stream.close() print("āœ“ Playback completed") return True except Exception as e: print(f"āŒ Playback error: {e}") return False finally: audio.terminate() def test_recording(): """Test microphone input""" print("\n" + "="*60) print("šŸŽ™ļø TESTING MICROPHONE RECORDING") print("="*60) audio = pyaudio.PyAudio() try: # Show device info info = audio.get_device_info_by_index(HIFIBERRY_INDEX) print(f"\nUsing device: {info['name']}") print(f"Max input channels: {info['maxInputChannels']}") # Record print("\nšŸ”“ Recording for 5 seconds...") print(" SPEAK NOW or make noise near the microphone...") stream = audio.open( format=pyaudio.paInt16, channels=1, rate=SAMPLE_RATE, input=True, input_device_index=HIFIBERRY_INDEX, frames_per_buffer=1024 ) frames = [] for i in range(0, int(SAMPLE_RATE / 1024 * 5)): data = stream.read(1024, exception_on_overflow=False) frames.append(data) stream.stop_stream() stream.close() print("āœ“ Recording completed") # Save to file filename = "/tmp/test_recording.wav" wf = wave.open(filename, 'wb') wf.setnchannels(1) wf.setsampwidth(audio.get_sample_size(pyaudio.paInt16)) wf.setframerate(SAMPLE_RATE) wf.writeframes(b''.join(frames)) wf.close() print(f"āœ“ Saved to {filename}") # Calculate volume level audio_data = np.frombuffer(b''.join(frames), dtype=np.int16) volume = np.abs(audio_data).mean() max_volume = np.abs(audio_data).max() print(f"\nRecording analysis:") print(f" Average level: {volume:.0f}") print(f" Peak level: {max_volume}") if max_volume > 1000: print(" āœ“ Good signal detected!") else: print(" āš ļø Very low signal - microphone might not be working") audio.terminate() # Play back print("\nšŸ”Š Playing back your recording...") audio = pyaudio.PyAudio() wf = wave.open(filename, 'rb') stream = audio.open( format=audio.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True, output_device_index=HIFIBERRY_INDEX ) data = wf.readframes(1024) while data: stream.write(data) data = wf.readframes(1024) stream.stop_stream() stream.close() wf.close() print("āœ“ Playback of recording completed") print(f"\nYou can listen again with: aplay {filename}") return True except Exception as e: print(f"āŒ Recording error: {e}") return False finally: audio.terminate() def test_dial_tone(): """Test classic dial tone (350Hz + 440Hz)""" print("\n" + "="*60) print("šŸ“ž TESTING DIAL TONE") print("="*60) audio = pyaudio.PyAudio() try: print("\nGenerating classic dial tone (350Hz + 440Hz)...") duration = 3 t = np.linspace(0, duration, int(SAMPLE_RATE * duration), False) # Generate two frequencies tone1 = np.sin(2 * np.pi * 350 * t) tone2 = np.sin(2 * np.pi * 440 * t) tone = (tone1 + tone2) / 2 tone = (tone * 0.3 * 32767).astype(np.int16) stream = audio.open( format=pyaudio.paInt16, channels=1, rate=SAMPLE_RATE, output=True, output_device_index=HIFIBERRY_INDEX, frames_per_buffer=1024 ) print("šŸŽµ Playing dial tone - This is what you'll hear when picking up the phone!") chunk_size = 2048 for i in range(0, len(tone.tobytes()), chunk_size): stream.write(tone.tobytes()[i:i + chunk_size]) stream.stop_stream() stream.close() print("āœ“ Dial tone playback completed") return True except Exception as e: print(f"āŒ Dial tone error: {e}") return False finally: audio.terminate() def show_device_info(): """Show all audio devices""" print("\n" + "="*60) print("šŸ“‹ AUDIO DEVICES ON YOUR SYSTEM") print("="*60) audio = pyaudio.PyAudio() print("\nAll devices:") for i in range(audio.get_device_count()): info = audio.get_device_info_by_index(i) device_type = [] if info['maxOutputChannels'] > 0: device_type.append("OUTPUT") if info['maxInputChannels'] > 0: device_type.append("INPUT") marker = " ← USING THIS" if i == HIFIBERRY_INDEX else "" print(f" [{i}] {info['name']}{marker}") print(f" Type: {', '.join(device_type)}") print(f" Sample rate: {info['defaultSampleRate']}") print() audio.terminate() def main(): """Main test routine""" print("\n" + "="*60) print("šŸŽ›ļø HIFIBERRY COMPLETE SYSTEM TEST") print("="*60) print(f"\nTesting HiFiBerry at device index: {HIFIBERRY_INDEX}") # Show devices show_device_info() input("\nPress Enter to start tests...") # Test 1: Playback test1 = test_playback() time.sleep(1) # Test 2: Dial tone test2 = test_dial_tone() time.sleep(1) # Test 3: Recording test3 = test_recording() # Summary print("\n" + "="*60) print("šŸ“Š TEST SUMMARY") print("="*60) print(f"\nāœ“ Speaker playback: {'PASS āœ“' if test1 else 'FAIL āŒ'}") print(f"āœ“ Dial tone: {'PASS āœ“' if test2 else 'FAIL āŒ'}") print(f"āœ“ Microphone recording: {'PASS āœ“' if test3 else 'FAIL āŒ'}") if test1 and test2 and test3: print("\nšŸŽ‰ ALL TESTS PASSED!") print("\nYour rotary phone system is ready to use!") print("Run: python3 rotary_phone_web.py") else: print("\nāš ļø Some tests failed. Check the output above for details.") print("\n" + "="*60) if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n\nTest interrupted by user") except Exception as e: print(f"\nāŒ Error: {e}") import traceback traceback.print_exc()