Conversation
|
Oh wow this looks great, I'll try it out asap! |
|
Cool! I forgot that you have to configure buildroot to also build a c++ stdlib which is then linked statically as I was unable to create a new linux image. My current development setup is sadly WSL-based, therefore I can only debug on the real device with serial line; which is quite combersome. I was not able to create/build a buildroot config that uses anything more modern than 2018.X. I am slowly refactoring some of the action-mapping code (to get to some json compatible enums etc). Do you remember what the edge states meant that are passed around as unsigned char? 0 is FallingEdge, 1 is Raising? But there are also some values like 3 and 4, I haven't groked that part yet. Thanks & cheers! |
|
Wow, thank you, amazing. |
Yeah I just omit the rear plate and have some wires dangling out. Not pretty but it works! You could probably do something neater if you drilled a hole and added some kind of connector for serial, maybe just another 3.5 TRS |
|
The issue was more that the connector to the serial header was physically interfering with the platter attachment/encoder. but I solved it and soldered the cables directly to the board. I should now be able to debug the current issues. Thanks! |
- Add diff sanity check: snap target_position if >0.5s from position - Fix position wrapping: use fmod instead of single subtraction for short loops with high pitch values - Reset cap_touch on track changes to force angle_offset recalculation - Document encoder glitch protection chain across affected files
Add the new sc1000-named files to complete the migration: - S50sc1000 init script - sc1000-import scripts - sc1000 binary placeholder - sc1000-boot updater script
- Replace ActionState static globals with InputState class owned by sc1000 - Update dispatch_event/perform_action_for_deck to take InputState reference - Convert rt and rig free functions to struct member functions - Convert sc1000 free functions to struct member functions - Replace #ifndef/#define include guards with #pragma once - Remove extern "C" blocks (codebase is now pure C++) - Replace typedef with using for type aliases - Update MidiController to access InputState through rt->engine
- Reset player.stopped when loading new track/loop so scratching works immediately without needing to press play first - Fix deploy.sh build output capture (redirect status messages to stderr)
Organize the ~30 fields in player and deck structs into logical groups for clarity and maintainability: Player substates (player_state.h): - PlaybackMode enum (STOPPED, PLAYING, SCRATCHING) - PositionState (current, target, offset, last_difference) - PitchState (current, sync, fader, note, bend, motor_speed) - VolumeState (set, fader_target, fader_current) - PlatterState (touched, touched_prev with helper methods) - RecordingState (requested, active, use_loop) - FeedbackState (beep_type, beep_position) Deck substates (deck_state.h): - NavigationState (folder_idx, file_idx, files_present) - EncoderState (angle, angle_raw, offset) - LoopState (track pointer) Each state group has a reset() method for centralized initialization. Legacy field aliases maintain full backward compatibility while allowing gradual migration to the new grouped structure.
Refactor player state into distinct input and output ownership: - Add DeckInput struct (deck_input.h) for all input-thread-written state: encoder, transport, pitch, volume, source selection, and requests - Expand DeckProcessingState (deck_processing_state.h) for audio engine output: position, pitch, volume, recording, and feedback state - Add query API to AudioEngine/AudioHardware for external code to read output state (get_position, get_pitch, get_volume, get_deck_state) - Update actions.cpp, deck.cpp, sc_input.cpp, sc1000.cpp to write to player.input.* instead of legacy player.*_state fields - Update alsa.cpp to use query API for CV output and monitoring volume - Migrate use_loop flag to input.source (PlaybackSource enum) - Migrate feedback_state.beep_type to input.beep_request This establishes clear data flow: Input thread -> DeckInput -> AudioEngine -> DeckProcessingState -> Query API Legacy sync-back to old player fields remains for gradual migration.
Replace recording_state.requested/active toggle with one-shot requests: - deck::record() now takes engine parameter to query recording state - Sets input.record_start or input.record_stop based on current state - State machine in sc1000.cpp processes requests and clears them - Recording state is queried via AudioHardware::is_recording() Mark deprecated legacy state structs: - RecordingState: fields replaced by input.record_start/stop and input.source - FeedbackState: fields replaced by input.beep_request
Complete the input/output state separation: - Remove sync-back from audio_engine.cpp (pos_state, pitch_state, etc.) - Update deck cue methods to take engine parameter and use query API: - is_locked(), recue(), clone(), cue(), punch_in(), punch_out() - Get elapsed/position from AudioHardware::get_deck_state() - Set offset via player.input.position_offset - Mark player helper functions as deprecated (get_elapsed, is_active, etc.) - Remove commented-out dead code in sc_input.cpp External code now exclusively uses query API for output state.
- Remove deprecated RecordingState and FeedbackState structs - Remove unused player helper functions (get_elapsed, is_active, etc.) - Add max_volume setting for output level control - Fix volume_knob initialization from settings->initial_volume - Apply volume_knob in audio engine volume calculation - Replace #define macros in sc_input.cpp with proper C++ members - Add ButtonMachineState enum for button state machine - Convert fader_open flags to bool type
Test infrastructure for deterministic audio engine testing: - TestAudioBackend: mock AudioHardware rendering to memory - InputSequence: scripted input events (encoder, touch, ADC) - Test sample generators (sine, sweep) with DFT analysis - WAV export for external analysis (--dump flag) - Python spectral analysis script with STFT plots - Automated test runner script Tests verify pitch scaling, scratching, and MIDI control.
Devices like MPK mini Plus enumerate as ALSA cards but have no audio output capability (output_channels=0). Previously these would match by card number or name substring, causing ALSA open errors. Now check output_channels > 0 before accepting a device match in both explicit hw:N matching and fallback name substring matching.
Split sc_input.cpp into separate layers: - sc_hardware.h/cpp: HardwareInput abstract class with SC1000Hardware impl - midi_input.h/cpp: Generic MIDI device enumeration and event processing - sc_input.cpp: Thin coordinator using polymorphic hardware interface All SC1000-specific state (button debounce, PIC readings, blip filter) is now private to SC1000Hardware. The input thread coordinator is hardware-agnostic, enabling future support for different platforms (motorized platter, etc.).
- Remove unused deck fields: protect, ncontrol, control[] - Remove legacy beep macros (BEEP_NONE, etc.) - use BeepType enum - Convert int→bool: platter_enabled, disable_volume_adc, disable_pic_buttons, jog_reverse in sc_settings - Remove legacy player state structs (PositionState, PitchState, VolumeState, PlatterState) - all state now in unified DeckInput - Delete player_state.h (no longer needed) - Replace sentinel values with std::optional: - deck::punch now std::optional<double> - Cues::get() returns std::optional<double> - Remove get_or_unset(), rename CUE_UNSET to CUE_FILE_UNSET
- Rename structs to CamelCase: Track, TrackBlock, Player, Deck, Sc1000, ScSettings, Mapping, AudioInterface, LoopBuffer, etc. - Convert track.h/cpp from C to modern C++ (constexpr, remove extern "C" blocks, remove #ifdef __cplusplus guards) - Replace C-style void parameter lists with empty parentheses - Convert if-else chains to switch statements in actions.cpp
- Update docker build script to use CMake instead of Make - Add explicit -O3 for Release builds in CMakeLists.txt - Add -flto to link options for proper LTO - Remove legacy Makefile-based build system - Remove obsolete xwax scripts and documentation - Remove debug/profiling artifacts (gmon.out, csv files) - Add .gitignore for build dirs and IDE files - Keep original_version/ as reference for xwax code
Use LINK_FLAGS property instead of target_link_options which requires CMake 3.13+. The Docker container has CMake 3.10.
Auto-cue mode: - Divide track into 4/8/16/32 equal parts for beat slicing - Toggle with Cue 1+2 (scratch deck) or Cue 3+4 (beat deck) - MIDI cues trigger jumps to calculated positions - Add parameter field to GPIO mappings for button index ALSA fixes: - Call snd_pcm_drop() before snd_pcm_close() for clean release - Implement AlsaAudio::stop() to properly stop PCM on shutdown - Add snd_config_update_free_global() on exit Startup volume: - Default volume_knob, crossfader, fader_current to 0 (muted) - player.init() sets initial_volume and opens crossfader - Prevents loud audio burst before input thread starts Bug fixes: - Fix settings file path casing (sc_settings.json) - Fix log file path (sc1000.log) - Initialize card_id in ALSA device scanning
|
Some fixes, updated the updater and added simple "auto cue markers" so you can slice up a sample (the mode toggles between cue markers from file and 4/8/16/32 equal divisions). There is also a bit more hardware abstraction going on, if one may "port" this over. |
- Fix CV crossfader output using audio volume instead of fader position - Fix SC500 volume squared bug (crossfader was set to volume_knob) - Handle track wrap in position control mode (shortest path diff) - Clamp scratch pitch to ±5x to prevent oscillation - Add diagnostic logging for prolonged low volume conditions - Fix fader_current reset() consistency
New setting controls maximum pitch multiplier during scratching. Higher values give snappier response to quick movements. Default: 10.0 (was hardcoded 5.0)
Hey,
this is an ongoing but slow-motion development from my side, just wanted to raise awareness. Currently the main improvements are USB audio support, vectorized audio engine for more CPU headroom; quite a bit of refactoring and getting rid of unnecessary/unused code, some stuff was rewritten in C++.
I am working towards:
Ideally I'd add/look into:
cheers!