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
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}Additional examples can be found in: