playing audio

main
_ 2021-11-12 14:33:38 -06:00
parent 15980d347c
commit b11c4ac0b8
4 changed files with 71 additions and 16 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/target /target
*.m4a
*.opus *.opus

7
Cargo.lock generated
View File

@ -88,6 +88,12 @@ version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.1.0" version = "1.1.0"
@ -421,6 +427,7 @@ name = "music_player"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"byteorder",
"cpal", "cpal",
"ffmpeg-next", "ffmpeg-next",
] ]

View File

@ -7,5 +7,6 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.45" anyhow = "1.0.45"
byteorder = "1.4.3"
cpal = "0.13.4" cpal = "0.13.4"
ffmpeg-next = "4.4.0" ffmpeg-next = "4.4.0"

View File

@ -1,4 +1,5 @@
use std::{ use std::{
io::Cursor,
sync::{ sync::{
Arc, Arc,
Condvar, Condvar,
@ -13,6 +14,11 @@ use anyhow::{
Result, Result,
}; };
use byteorder::{
LittleEndian,
ReadBytesExt,
};
use cpal::traits::{ use cpal::traits::{
DeviceTrait, DeviceTrait,
HostTrait, HostTrait,
@ -74,25 +80,35 @@ fn main () -> Result <()> {
let pair2 = Arc::clone (&pair); let pair2 = Arc::clone (&pair);
let thread_decoder = thread::spawn (move|| { let thread_decoder = thread::spawn (move|| {
/*
Pipeline:
- demuxer
- decoder
- resampler
- cpal
*/
let (lock, cvar) = &*pair2; let (lock, cvar) = &*pair2;
let freq = 75; let mut input_ctx = ffmpeg_next::format::input (&"test.m4a")?;
let period = SAMPLE_RATE / freq; let stream = input_ctx
.streams ()
.best (ffmpeg_next::media::Type::Audio)
.ok_or_else (|| anyhow! ("can't find good audio stream"))?;
let best_stream_idx = stream.index ();
let mut saw_counter = 0; let mut decoder = stream.codec ().decoder ().audio ()?;
let mut resampler = decoder.resampler (
ffmpeg_next::util::format::sample::Sample::F32 (
ffmpeg_next::util::format::sample::Type::Packed,
),
ffmpeg_next::util::channel_layout::ChannelLayout::STEREO,
48000,
)?;
let mut frame = ffmpeg_next::util::frame::Audio::empty ();
let mut packets = input_ctx.packets ();
loop { loop {
let mut buffer = vec! [0.0f32; 4000];
for x in &mut buffer {
*x = 0.25 * (saw_counter as f32 * 2.0 / period as f32 - 1.0);
saw_counter += 1;
if saw_counter >= period {
saw_counter = 0
}
}
// eprintln! ("decode thread parking"); // eprintln! ("decode thread parking");
let mut pcm_buffers = cvar.wait_while (lock.lock ().unwrap (), |pcm_buffers| { let mut pcm_buffers = cvar.wait_while (lock.lock ().unwrap (), |pcm_buffers| {
@ -100,8 +116,38 @@ fn main () -> Result <()> {
pcm_buffers.samples_available () >= 48_000 pcm_buffers.samples_available () >= 48_000
}).unwrap (); }).unwrap ();
// dbg! (pcm_buffers.samples_available ()); let mut did_anything = false;
pcm_buffers.produce (buffer);
while decoder.receive_frame (&mut frame).is_ok () {
did_anything = true;
let mut buffer = vec! [0.0f32; frame.plane::<f32> (0).len () * 2];
let mut rdr_left = frame.plane::<f32> (0).iter ();
let mut rdr_right = frame.plane::<f32> (1).iter ();
for x in buffer.chunks_mut (2) {
x [0] = *rdr_left.next ().unwrap ();
x [1] = *rdr_right.next ().unwrap ();
}
pcm_buffers.produce (buffer);
}
match packets.next () {
None => {},
Some ((stream, packet)) => {
did_anything = true;
if stream.index () == best_stream_idx {
decoder.send_packet (&packet)?;
}
},
}
if ! did_anything {
break;
}
} }
Ok::<_, anyhow::Error> (()) Ok::<_, anyhow::Error> (())