How Export Configuration Options Like Sample Rate and Channels Are Applied in Muse
Export configuration options like sample rate and channels are captured from the Export Config Sheet UI, stored in AudioSampleMetadata, and applied by AudioExportPipeline to configure both WAV headers and MP3 encoding parameters.
When exporting audio in the Muse app, users select specific export configuration options like sample rate and channels through the Export Config Sheet. These settings propagate from the Kotlin Multiplatform UI layer down to platform-specific audio encoders to ensure the final output matches user expectations exactly according to the kkoshin/muse source code.
How Export Configuration Options Flow Through the Pipeline
Capturing Settings in ExportConfigSheet
In muse/src/commonMain/kotlin/io/github/kkoshin/muse/feature/editor/ExportConfigSheet.kt, the composable UI gathers user selections into an ExportConfigSheetArgs data class. This object encapsulates the chosen sample rate (e.g., 44100 Hz, 48000 Hz) and channel count (1 for mono, 2 for stereo), passing them from the sheet to the ViewModel layer.
Propagating Metadata via ExportViewModel
The ExportViewModel receives these arguments and constructs an AudioSampleMetadata instance. This data class (defined in AudioSampleMetadata.kt) serves as the single source of truth for the export pipeline:
val sampleRateInHz: Int // e.g., 44100, 48000
val channelCount: Int // 1 = mono, 2 = stereo
The ViewModel initializes AudioExportPipeline with this metadata, ensuring all downstream components receive consistent configuration parameters regardless of the target output format.
Applying Export Configuration Options to Audio Outputs
Writing WAV Headers with WaveHeaderWriter
For WAV exports, WaveHeaderWriter constructs the RIFF header using the metadata values. Platform-specific implementations in muse/src/iosMain/kotlin/io/github/kkoshin/muse/audio/WaveHeaderWriter.ios.kt and muse/src/androidMain/kotlin/io/github/kkoshin/muse/audio/WaveHeaderWriter.android.kt write the sample rate to bytes 24-27 and channel count to byte 22:
val sampleRate = audioMetadata.sampleRateInHz.toLong()
val channels = audioMetadata.channelCount
// Sample rate (little-endian)
header[24] = (sampleRate and 0xFF).toByte()
header[25] = ((sampleRate shr 8) and 0xFF).toByte()
header[26] = ((sampleRate shr 16) and 0xFF).toByte()
header[27] = ((sampleRate shr 24) and 0xFF).toByte()
// Channel count
header[22] = channels.toByte()
Configuring MP3 Encoding with Mp3Encoder
When exporting to MP3, Mp3Encoder (located in muse/src/iosMain/kotlin/io/github/kkoshin/muse/audio/Mp3Encoder.ios.kt and the corresponding Android path) forwards these parameters to the native LAME library:
// Configure LAME encoder with export settings
lame_set_in_samplerate(lame, wavParser.sampleRate)
lame_set_num_channels(lame, wavParser.channelCount)
The encoder reads these values from the WavParser instance, which itself derives them from the AudioSampleMetadata passed through the pipeline.
Pipeline Processing and Validation
During export, AudioExportPipeline uses AudioSampleMetadata to compute byte offsets and durations for any intermediate processing steps (such as silence trimming or padding). This ensures that transformations respect the configured sample rate and maintain audio synchronization throughout the export process.
Summary
- ExportConfigSheet captures user selections as
ExportConfigSheetArgsand passes them to the ViewModel. - ExportViewModel transforms UI arguments into
AudioSampleMetadatafor type-safe propagation through the export pipeline. - WaveHeaderWriter embeds sample rate and channel data into specific byte offsets of the WAV RIFF header.
- Mp3Encoder applies the same configuration to the LAME encoder via
lame_set_in_samplerateandlame_set_num_channels. - AudioExportPipeline maintains these settings throughout processing to ensure the final output matches the selected export configuration options.
Frequently Asked Questions
Where are export configuration options stored in the Muse codebase?
They are stored in the AudioSampleMetadata data class, which is instantiated by ExportViewModel based on the ExportConfigSheetArgs received from the UI. This object travels through AudioExportPipeline to reach platform-specific writers and encoders.
How does Muse apply sample rate settings to WAV files?
WaveHeaderWriter writes the sample rate to bytes 24-27 of the WAV header in little-endian format, using the sampleRateInHz value from AudioSampleMetadata. Separate implementations exist for iOS and Android in WaveHeaderWriter.ios.kt and WaveHeaderWriter.android.kt.
What controls channel configuration during MP3 export?
The Mp3Encoder configures the native LAME library using lame_set_num_channels, passing the channelCount from the parsed WAV source. This ensures the MP3 output maintains the user's selected mono or stereo configuration.
How do platform-specific implementations share export configuration?
Both iOS and Android implementations of WaveHeaderWriter and Mp3Encoder consume the same common AudioSampleMetadata class, ensuring consistent application of export configuration options like sample rate and channels across platforms while allowing platform-specific native code for file I/O and encoding.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →