This implementation adds professional audio interface support to the DJ Mixer application through PyAudio integration with ASIO (Audio Stream Input/Output) driver support. This enables low-latency audio processing and full control over audio device selection, making the application suitable for professional DJ setups.
A complete PyAudio-based audio engine with:
- PyAudioTrack: Audio track class that loads files into memory using pydub
- PyAudioMixer: Main mixer class with real-time audio mixing
- ASIO Support: Detection and use of ASIO-compatible devices
- Thread-Safe Design: Proper locking for concurrent audio callback operations
- Mock Mode: Automatic fallback for testing without real audio hardware
Key Features:
- Load audio files (MP3, WAV, OGG, FLAC)
- Real-time audio mixing via stream callback
- Device enumeration and selection
- Volume control (per-track and master)
- Crossfader support
- Playback control (play, stop, pause, unpause)
Extended EnhancedDJMixer to support both pygame and PyAudio modes:
- Added
use_pyaudioanduse_asioinitialization parameters - Wrapper methods that work with both backends
- ASIO device listing via
get_asio_devices() - Enhanced mixer status includes audio device information
- Backwards compatible with existing pygame mode
Usage:
# Use PyAudio with ASIO
mixer = EnhancedDJMixer(use_pyaudio=True, use_asio=True)
mixer.initialize()
# Or use traditional pygame mode
mixer = EnhancedDJMixer(use_pyaudio=False)
mixer.initialize()Test Suite Coverage:
-
test_pyaudio_mixer.py: 25 tests for PyAudioMixer class- Track initialization and loading
- Volume control
- Playback controls
- Device enumeration
- ASIO device detection
- Mixer initialization
-
test_enhanced_mixer_pyaudio.py: 11 tests for integration- PyAudio mode initialization
- ASIO mode initialization
- Device selection
- Playback control wrappers
- Status reporting
- Backwards compatibility
All 107 tests pass (excluding GUI tests that require tkinter)
README Updates:
- Added PyAudio/ASIO to feature list
- New "Audio Device Support" section
- Code examples for PyAudio usage
- Comparison of pygame vs PyAudio modes
Demo Script (demo_pyaudio_asio.py):
- Standard PyAudio mode demonstration
- ASIO mode demonstration
- Device enumeration examples
- Feature comparison
- Usage examples
Added to requirements.txt:
pyaudio>=0.2.13
The PyAudioMixer uses a real-time audio callback:
def _audio_callback(self, in_data, frame_count, time_info, status):
with self.lock:
# Mix all playing tracks
output = np.zeros((frame_count, self.channels), dtype=np.int16)
for track in self.tracks.values():
if track.is_playing:
chunk = track.get_audio_chunk(frame_count)
if chunk is not None:
# Add to mix with clipping prevention
output = np.clip(
output.astype(np.int32) + chunk.astype(np.int32),
-32768, 32767
).astype(np.int16)
# Apply master volume
if self.master_volume != 1.0:
output = (output * self.master_volume).astype(np.int16)
return (output.tobytes(), pyaudio.paContinue)# Initialize device manager
self.device_manager.initialize(use_mock=self.use_mock)
# Select ASIO device if requested
if use_asio:
asio_devices = self.device_manager.get_asio_devices()
if asio_devices:
self.output_device = asio_devices[0]The implementation gracefully falls back to mock mode when PyAudio is not available or fails to initialize, making it CI/CD friendly:
try:
import pyaudio
self.pyaudio_instance = pyaudio.PyAudio()
# ... initialize stream ...
except Exception as e:
print(f"Failed to initialize PyAudio mixer: {e}")
if not self.use_mock:
print("Falling back to mock mode")
self.use_mock = True
return self.initialize(device_index=device_index, use_asio=use_asio)- Low Latency: ASIO drivers reduce audio latency significantly
- Device Control: Choose specific audio interfaces for different outputs
- Multi-Channel Support: Utilize all channels of professional DJ controllers
- Stability: Direct hardware access without OS audio mixing
- Flexible: Works with or without PyAudio/ASIO
- Testable: Mock mode for CI/CD pipelines
- Backwards Compatible: Existing pygame code continues to work
- Extensible: Easy to add more audio processing features
- ✅ All tests passing: 107 tests pass
- ✅ Code formatted: Black formatting applied
- ✅ Security checked: Bandit reports no issues
- ✅ Type hints: Comprehensive type annotations
- ✅ Documentation: Docstrings for all public APIs
- ✅ Mock support: Works without real audio hardware
from enhanced_mixer import EnhancedDJMixer
# Initialize with PyAudio
mixer = EnhancedDJMixer(use_pyaudio=True)
mixer.initialize()
# Load and play tracks
mixer.load_track("deck1", "track1.mp3")
mixer.load_track("deck2", "track2.mp3")
mixer.play_track("deck1")
mixer.play_track("deck2")
# Control mixing
mixer.set_crossfader(0.5)
mixer.apply_crossfader("deck1", "deck2")
mixer.set_master_volume(0.8)
mixer.cleanup()# Use ASIO for professional audio interfaces
mixer = EnhancedDJMixer(use_pyaudio=True, use_asio=True)
mixer.initialize()
# List ASIO devices
asio_devices = mixer.get_asio_devices()
for device in asio_devices:
print(f"{device.name} - {device.max_output_channels} channels")
# Get mixer status with device info
status = mixer.get_mixer_status()
print(f"Using: {status['audio_device']['name']}")
print(f"Host API: {status['audio_device']['host_api']}")Potential future improvements:
- Per-track device routing (send deck1 to output 1, deck2 to output 2)
- Recording with PyAudio for better quality
- Real-time audio effects processing
- Buffer size adjustment for latency tuning
- Input device support for recording/sampling
- Multi-zone routing configurations
The implementation works across platforms:
- Windows: ASIO drivers for professional audio interfaces
- macOS: Core Audio with low latency
- Linux: ALSA/JACK support via PyAudio
- Mock Mode: Works everywhere for testing
This implementation successfully adds professional audio interface support to the DJ Mixer application while maintaining backwards compatibility with the existing pygame-based system. The code is well-tested, documented, and ready for production use.