Skip to main content

create_wav

Function create_wav 

Source
pub fn create_wav(data: Vec<u8>) -> Vec<u8> 
Expand description

Prepends a standard 44-byte RIFF/WAVE header to raw CD-DA PCM.

data must already contain headerless, signed 16-bit little-endian, interleaved stereo PCM sampled at 44,100 Hz. This function does not validate or convert the audio data; it only adds a header describing that format.

PCM returned by CdReader::read_track or the source-independent read_track function already has the required format. The returned vector contains a complete WAV file and can be written directly to a .wav file.

Examples found in repository?
examples/read_first_track.rs (line 20)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let output_dir = common::fresh_output_dir("read_first_track")?;
8    let reader = CdReader::open_default()?;
9    let toc = reader.read_toc()?;
10
11    let first_audio = toc
12        .tracks
13        .iter()
14        .find(|t| t.is_audio)
15        .ok_or("no audio tracks found")?;
16
17    println!("Reading track {}...", first_audio.number);
18    let data = reader.read_track(&toc, first_audio.number)?;
19
20    let wav = create_wav(data);
21    let output_path = output_dir.join(format!("track{:02}.wav", first_audio.number));
22    std::fs::write(&output_path, wav)?;
23    println!("Saved {}", output_path.display());
24
25    Ok(())
26}
More examples
Hide additional examples
examples/stream_last_track.rs (line 26)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let output_dir = common::fresh_output_dir("stream_last_track")?;
8    let reader = CdReader::open_default()?;
9    let toc = reader.read_toc()?;
10
11    let last_audio = toc
12        .tracks
13        .iter()
14        .rev()
15        .find(|t| t.is_audio)
16        .ok_or("no audio tracks found")?;
17
18    println!("Streaming track {}...", last_audio.number);
19    let mut stream = reader.open_track_stream(&toc, last_audio.number)?;
20
21    let mut pcm = Vec::new();
22    while let Some(chunk) = stream.next_chunk()? {
23        pcm.extend_from_slice(&chunk);
24    }
25
26    let wav = create_wav(pcm);
27    let output_path = output_dir.join(format!("track{:02}.wav", last_audio.number));
28    std::fs::write(&output_path, wav)?;
29    println!("Saved {}", output_path.display());
30
31    Ok(())
32}
examples/read_all_tracks.rs (line 20)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let output_dir = common::fresh_output_dir("read_all_tracks")?;
8    let reader = CdReader::open_default()?;
9    let toc = reader.read_toc()?;
10
11    let audio_tracks: Vec<_> = toc.tracks.iter().filter(|t| t.is_audio).collect();
12    println!("Found {} audio track(s)\n", audio_tracks.len());
13
14    let mut failed = Vec::new();
15
16    for track in &audio_tracks {
17        print!("Reading track {:>2}... ", track.number);
18        match reader.read_track(&toc, track.number) {
19            Ok(data) => {
20                let wav = create_wav(data);
21                let output_path = output_dir.join(format!("track{:02}.wav", track.number));
22                std::fs::write(&output_path, wav)?;
23                println!("saved {}", output_path.display());
24            }
25            Err(e) => {
26                println!("FAILED: {}", e);
27                failed.push(track.number);
28            }
29        }
30    }
31
32    if !failed.is_empty() {
33        eprintln!("\nFailed to read tracks: {:?}", failed);
34    }
35
36    Ok(())
37}
examples/custom_retry.rs (line 39)
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13    let output_dir = common::fresh_output_dir("custom_retry")?;
14    let reader = CdReader::open_default()?;
15    let toc = reader.read_toc()?;
16
17    let first_audio = toc
18        .tracks
19        .iter()
20        .find(|t| t.is_audio)
21        .ok_or("no audio tracks found")?;
22
23    // More attempts, longer backoff, and sector reduction down to 1
24    // for maximum resilience on scratched media.
25    let retry = RetryConfig::default()
26        .with_max_attempts(8)
27        .with_initial_backoff(Duration::from_millis(50))
28        .with_max_backoff(Duration::from_secs(1))
29        .with_chunk_reduction(true)
30        .with_min_sectors_per_read(1);
31    let options = ReadOptions::default().with_retry(retry);
32
33    println!(
34        "Reading track {} with aggressive retry...",
35        first_audio.number
36    );
37    let data = reader.read_track_with_options(&toc, first_audio.number, &options)?;
38
39    let wav = create_wav(data);
40    let output_path = output_dir.join(format!("track{:02}.wav", first_audio.number));
41    std::fs::write(&output_path, wav)?;
42    println!("Saved {}", output_path.display());
43
44    Ok(())
45}
examples/stream_with_progress.rs (line 37)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    let output_dir = common::fresh_output_dir("stream_with_progress")?;
8    let reader = CdReader::open_default()?;
9    let toc = reader.read_toc()?;
10
11    let first_audio = toc
12        .tracks
13        .iter()
14        .find(|t| t.is_audio)
15        .ok_or("no audio tracks found")?;
16
17    let mut stream = reader.open_track_stream(&toc, first_audio.number)?;
18
19    let total_secs = stream.total_seconds();
20    println!(
21        "Track {} — {} sectors ({:.0}s)\n",
22        first_audio.number,
23        stream.total_sectors(),
24        total_secs,
25    );
26
27    let mut pcm = Vec::new();
28    while let Some(chunk) = stream.next_chunk()? {
29        pcm.extend_from_slice(&chunk);
30
31        let cur = stream.current_seconds();
32        let pct = cur / total_secs * 100.0;
33        eprint!("\r  [{:>5.1}s / {:.1}s] {:5.1}%", cur, total_secs, pct,);
34    }
35    eprintln!("\r  [{:.1}s / {:.1}s] 100.0%", total_secs, total_secs);
36
37    let wav = create_wav(pcm);
38    let output_path = output_dir.join(format!("track{:02}.wav", first_audio.number));
39    std::fs::write(&output_path, wav)?;
40    println!("\nSaved {}", output_path.display());
41
42    Ok(())
43}
examples/play_audio_track.rs (line 69)
28fn main() -> Result<(), Box<dyn std::error::Error>> {
29    let output_dir = common::fresh_output_dir("play_audio_track")?;
30    let seconds: u32 = match std::env::args().nth(1) {
31        Some(a) => a.parse()?,
32        None => 30,
33    };
34
35    let reader = CdReader::open_default()?;
36    let toc = reader.read_toc()?;
37
38    let track = toc
39        .tracks
40        .iter()
41        .find(|t| t.is_audio)
42        .ok_or("no audio tracks found on this disc")?;
43
44    // Clamp the preview to what the track actually holds: the track ends where
45    // the next track starts, or at the lead-out if it's the last one.
46    let track_end = toc
47        .tracks
48        .iter()
49        .map(|t| t.start_lba)
50        .filter(|&lba| lba > track.start_lba)
51        .min()
52        .unwrap_or(toc.leadout_lba);
53    let track_sectors = track_end - track.start_lba;
54    let sectors = (seconds * SECTORS_PER_SECOND).min(track_sectors);
55    let actual_seconds = sectors / SECTORS_PER_SECOND;
56
57    println!(
58        "Reading first {actual_seconds}s ({sectors} sectors) of audio track #{}...",
59        track.number
60    );
61    let pcm = reader.read_sector_range(track.start_lba, sectors, &ReadOptions::default())?;
62    println!(
63        "Read {} bytes of PCM ({:.1} MiB)",
64        pcm.len(),
65        pcm.len() as f64 / (1024.0 * 1024.0)
66    );
67
68    let output_path = output_dir.join(format!("track{:02}_preview.wav", track.number));
69    std::fs::write(&output_path, create_wav(pcm))?;
70    println!("Saved {}", output_path.display());
71
72    play(&output_path)
73}