[Feature Request] Audio Extraction #22

Closed
opened 2026-01-30 21:22:56 +00:00 by claunia · 2 comments
Owner

Originally created by @mnadareski on GitHub (Jun 28, 2021).

Export audio to WAV and/or FLAC

Originally created by @mnadareski on GitHub (Jun 28, 2021). Export audio to WAV and/or FLAC
Author
Owner

@mnadareski commented on GitHub (Jun 28, 2021):

Will likely rely on https://github.com/aaru-dps/Aaru/issues/353

@mnadareski commented on GitHub (Jun 28, 2021): Will likely rely on https://github.com/aaru-dps/Aaru/issues/353
Author
Owner

@mnadareski commented on GitHub (Jul 31, 2021):

Potential solution is using CSCore's WAV output.

OpticalDiscBase.cs:

/// <summary>
/// Extract a track to WAV
/// </summary>
/// <param name="trackNumber">Track number to extract</param>
/// <param name="outputDirectory">Output path to write data to</param
public abstract void ExtractTrackToWav(uint trackNumber, string outputDirectory);

/// <summary>
/// Extract all tracks to WAV
/// </summary>
/// <param name="outputDirectory">Output path to write data to</param
public abstract void ExtractAllTracksToWav(string outputDirectory);

CompactDisc.cs:

/// <inheritdoc/>
public override void ExtractTrackToWav(uint trackNumber, string outputDirectory)
{
	if(_image == null)
		return;

	// Get the track with that value, if possible
	Track track = _image.Tracks.FirstOrDefault(t => t.TrackSequence == trackNumber);

	// If the track isn't valid, we can't do anything
	if(track == null || track.TrackType != TrackType.Audio)
		return;

	// Read in the track data to a buffer
	uint length = (uint)(track.TrackEndSector - track.TrackStartSector);
	byte[] buffer = _image.ReadSectors(track.TrackStartSector, length);

	// Build the WAV output
	string filename = Path.Combine(outputDirectory, $"Track {trackNumber.ToString().PadLeft(2, '0')}.wav");
	using(WaveWriter waveWriter = new WaveWriter(filename, new CSCore.WaveFormat()))
	{
		// Write out to the file
		waveWriter.Write(buffer, 0, buffer.Length);
	}
}

/// <inheritdoc/>
public override void ExtractAllTracksToWav(string outputDirectory)
{
	if(_image == null)
		return;

	foreach(Track track in _image.Tracks)
	{
		ExtractTrackToWav(track.TrackSequence, outputDirectory);
	}
}

Player.cs:

/// <summary>
/// Extract a single track from the image to WAV
/// </summary>
/// <param name="trackNumber"></param>
/// <param name="outputDirectory">Output path to write data to</param
public void ExtractSingleTrackToWav(uint trackNumber, string outputDirectory) => _opticalDisc?.ExtractTrackToWav(trackNumber, outputDirectory);

/// <summary>
/// Extract all tracks from the image to WAV
/// </summary>
/// <param name="outputDirectory">Output path to write data to</param
public void ExtractAllTracksToWav(string outputDirectory) => _opticalDisc?.ExtractAllTracksToWav(outputDirectory);

PlayerViewModel.cs:

/// <summary>
/// Extract a single track from the image to WAV
/// </summary>
/// <param name="trackNumber"></param>
/// <param name="outputDirectory">Output path to write data to</param
public void ExtractSingleTrackToWav(uint trackNumber, string outputDirectory) => _player?.ExtractSingleTrackToWav(trackNumber, outputDirectory);

/// <summary>
/// Extract all tracks from the image to WAV
/// </summary>
/// <param name="outputDirectory">Output path to write data to</param
public void ExtractAllTracksToWav(string outputDirectory) => _player?.ExtractAllTracksToWav(outputDirectory);

MainViewModel.cs:ExecuteKeyPress (change to async):

// Save track(s)
else if (e.Key == App.Settings.SaveTrackKey)
{
	if(PlayerView?.ViewModel == null)
		return;

	var dialog = new OpenFolderDialog();
	string path = await dialog.ShowAsync(App.MainWindow);
	if(string.IsNullOrWhiteSpace(path))
		return;

	if(e.KeyModifiers.HasFlag(KeyModifiers.Shift))
		PlayerView.ViewModel.ExtractAllTracksToWav(path);
	else
		PlayerView.ViewModel.ExtractSingleTrackToWav((uint)PlayerView.ViewModel.CurrentTrackNumber, path);
}

SettingsViewModel.cs (after LoadImageKey):

/// <summary>
/// Key assigned to save the current track or all tracks
/// </summary>
public Key SaveTrackKey { get; set; } = Key.S;

SettingsWindow.xaml (after Load Image):

<!-- Save Track -->
<TextBlock Grid.Row="1" Grid.Column="0" Width="120">Save Track(s)</TextBlock>
<ComboBox Grid.Row="1" Grid.Column="1" Name="SaveTrackKeyBind"
		  Items="{Binding KeyboardList}" SelectedItem="{Binding SaveTrackKey, Mode=TwoWay}"
		  HorizontalAlignment="Right" Margin="8,0,0,0" Width="120"/>
@mnadareski commented on GitHub (Jul 31, 2021): Potential solution is using CSCore's WAV output. `OpticalDiscBase.cs`: ``` /// <summary> /// Extract a track to WAV /// </summary> /// <param name="trackNumber">Track number to extract</param> /// <param name="outputDirectory">Output path to write data to</param public abstract void ExtractTrackToWav(uint trackNumber, string outputDirectory); /// <summary> /// Extract all tracks to WAV /// </summary> /// <param name="outputDirectory">Output path to write data to</param public abstract void ExtractAllTracksToWav(string outputDirectory); ``` `CompactDisc.cs`: ``` /// <inheritdoc/> public override void ExtractTrackToWav(uint trackNumber, string outputDirectory) { if(_image == null) return; // Get the track with that value, if possible Track track = _image.Tracks.FirstOrDefault(t => t.TrackSequence == trackNumber); // If the track isn't valid, we can't do anything if(track == null || track.TrackType != TrackType.Audio) return; // Read in the track data to a buffer uint length = (uint)(track.TrackEndSector - track.TrackStartSector); byte[] buffer = _image.ReadSectors(track.TrackStartSector, length); // Build the WAV output string filename = Path.Combine(outputDirectory, $"Track {trackNumber.ToString().PadLeft(2, '0')}.wav"); using(WaveWriter waveWriter = new WaveWriter(filename, new CSCore.WaveFormat())) { // Write out to the file waveWriter.Write(buffer, 0, buffer.Length); } } /// <inheritdoc/> public override void ExtractAllTracksToWav(string outputDirectory) { if(_image == null) return; foreach(Track track in _image.Tracks) { ExtractTrackToWav(track.TrackSequence, outputDirectory); } } ``` `Player.cs`: ``` /// <summary> /// Extract a single track from the image to WAV /// </summary> /// <param name="trackNumber"></param> /// <param name="outputDirectory">Output path to write data to</param public void ExtractSingleTrackToWav(uint trackNumber, string outputDirectory) => _opticalDisc?.ExtractTrackToWav(trackNumber, outputDirectory); /// <summary> /// Extract all tracks from the image to WAV /// </summary> /// <param name="outputDirectory">Output path to write data to</param public void ExtractAllTracksToWav(string outputDirectory) => _opticalDisc?.ExtractAllTracksToWav(outputDirectory); ``` `PlayerViewModel.cs`: ``` /// <summary> /// Extract a single track from the image to WAV /// </summary> /// <param name="trackNumber"></param> /// <param name="outputDirectory">Output path to write data to</param public void ExtractSingleTrackToWav(uint trackNumber, string outputDirectory) => _player?.ExtractSingleTrackToWav(trackNumber, outputDirectory); /// <summary> /// Extract all tracks from the image to WAV /// </summary> /// <param name="outputDirectory">Output path to write data to</param public void ExtractAllTracksToWav(string outputDirectory) => _player?.ExtractAllTracksToWav(outputDirectory); ``` `MainViewModel.cs:ExecuteKeyPress` (change to `async`): ``` // Save track(s) else if (e.Key == App.Settings.SaveTrackKey) { if(PlayerView?.ViewModel == null) return; var dialog = new OpenFolderDialog(); string path = await dialog.ShowAsync(App.MainWindow); if(string.IsNullOrWhiteSpace(path)) return; if(e.KeyModifiers.HasFlag(KeyModifiers.Shift)) PlayerView.ViewModel.ExtractAllTracksToWav(path); else PlayerView.ViewModel.ExtractSingleTrackToWav((uint)PlayerView.ViewModel.CurrentTrackNumber, path); } ``` `SettingsViewModel.cs` (after `LoadImageKey`): ``` /// <summary> /// Key assigned to save the current track or all tracks /// </summary> public Key SaveTrackKey { get; set; } = Key.S; ``` `SettingsWindow.xaml` (after Load Image): ``` <!-- Save Track --> <TextBlock Grid.Row="1" Grid.Column="0" Width="120">Save Track(s)</TextBlock> <ComboBox Grid.Row="1" Grid.Column="1" Name="SaveTrackKeyBind" Items="{Binding KeyboardList}" SelectedItem="{Binding SaveTrackKey, Mode=TwoWay}" HorizontalAlignment="Right" Margin="8,0,0,0" Width="120"/> ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: aaru-dps/RedBookPlayer#22