add sine example
This commit is contained in:
commit
f5c4ff8c35
3 changed files with 133 additions and 0 deletions
2
01-play-sine/.gitignore
vendored
Normal file
2
01-play-sine/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
Cargo.lock
|
7
01-play-sine/Cargo.toml
Normal file
7
01-play-sine/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "play-sine"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
pipewire = "0.8.0"
|
124
01-play-sine/src/main.rs
Normal file
124
01-play-sine/src/main.rs
Normal file
|
@ -0,0 +1,124 @@
|
|||
use std::io::Cursor;
|
||||
|
||||
use pipewire::{
|
||||
context::Context,
|
||||
main_loop::MainLoop,
|
||||
properties::properties,
|
||||
spa::{
|
||||
param::audio::{AudioFormat, AudioInfoRaw},
|
||||
pod::{serialize::PodSerializer, Object, Pod, Value},
|
||||
sys::{SPA_PARAM_EnumFormat, SPA_TYPE_OBJECT_Format},
|
||||
utils::Direction,
|
||||
},
|
||||
stream::{Stream, StreamFlags},
|
||||
};
|
||||
|
||||
struct MyData {
|
||||
time: u64,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mainloop = MainLoop::new(None)?;
|
||||
let context = Context::new(&mainloop)?;
|
||||
let core = context.connect(None)?;
|
||||
let registry = core.get_registry()?;
|
||||
|
||||
let _global_listener = registry
|
||||
.add_listener_local()
|
||||
.global(|global| println!("New global: {:?}", global))
|
||||
.register();
|
||||
|
||||
let sample_rate = 48000;
|
||||
let channel_count = 2;
|
||||
|
||||
let mut audio_info = AudioInfoRaw::new();
|
||||
audio_info.set_format(AudioFormat::F32LE);
|
||||
audio_info.set_rate(sample_rate);
|
||||
audio_info.set_channels(channel_count);
|
||||
|
||||
let param_bytes = PodSerializer::serialize(
|
||||
Cursor::new(vec![]),
|
||||
&Value::Object(Object {
|
||||
type_: SPA_TYPE_OBJECT_Format,
|
||||
id: SPA_PARAM_EnumFormat,
|
||||
properties: audio_info.into(),
|
||||
}),
|
||||
)
|
||||
.expect("failed to serialize param")
|
||||
.0
|
||||
.into_inner();
|
||||
|
||||
let mut params = vec![Pod::from_bytes(¶m_bytes).expect("failed to create pod")];
|
||||
|
||||
let out_stream = Stream::new(
|
||||
&core,
|
||||
"out1",
|
||||
properties! {
|
||||
*pipewire::keys::MEDIA_TYPE => "Audio",
|
||||
*pipewire::keys::MEDIA_CATEGORY => "Playback",
|
||||
*pipewire::keys::MEDIA_ROLE => "Music"
|
||||
},
|
||||
)
|
||||
.expect("failed to create stream");
|
||||
|
||||
out_stream
|
||||
.connect(
|
||||
Direction::Output,
|
||||
None,
|
||||
StreamFlags::AUTOCONNECT | StreamFlags::MAP_BUFFERS | StreamFlags::RT_PROCESS,
|
||||
params.as_mut_slice(),
|
||||
)
|
||||
.expect("failed to connect stream");
|
||||
|
||||
let my_data = MyData { time: 0 };
|
||||
|
||||
let _out_stream_listener = out_stream
|
||||
.add_local_listener_with_user_data(my_data)
|
||||
.process(move |stream, my_data: &mut MyData| {
|
||||
let mut buffer = match stream.dequeue_buffer() {
|
||||
Some(buf) => buf,
|
||||
None => {
|
||||
eprintln!("stream is out of buffers");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let stride = std::mem::size_of::<f32>() * (channel_count as usize);
|
||||
let datas = buffer.datas_mut();
|
||||
|
||||
let data = &mut datas[0];
|
||||
|
||||
let mut samples_written = 0;
|
||||
if let Some(slice) = data.data() {
|
||||
let slice = unsafe { &mut *(slice as *mut _ as *mut [f32]) };
|
||||
|
||||
for i in 0..(slice.len() / stride) {
|
||||
let time_samples = {
|
||||
let t = my_data.time;
|
||||
my_data.time += 1;
|
||||
t
|
||||
};
|
||||
let time_secs = (time_samples as f32) / 48000.0 as f32;
|
||||
let sine_freq = 440.0;
|
||||
let pi2 = 2.0 * 3.141;
|
||||
let phi = pi2 * time_secs * sine_freq;
|
||||
let value = 0.5 + 0.5 * f32::sin(phi);
|
||||
|
||||
slice[2 * i] = value;
|
||||
slice[2 * i + 1] = value;
|
||||
samples_written += 2;
|
||||
}
|
||||
}
|
||||
|
||||
let chunk = data.chunk_mut();
|
||||
*chunk.offset_mut() = 0;
|
||||
*chunk.stride_mut() = stride as _;
|
||||
*chunk.size_mut() = (stride * samples_written) as _;
|
||||
})
|
||||
.register()
|
||||
.expect("failed to add listener");
|
||||
|
||||
mainloop.run();
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue