2024-12-15 23:52:17 -05:00
use anyhow ::{ Context , Result } ;
use cpal ::traits ::{ DeviceTrait , HostTrait , StreamTrait } ;
use cpal ::{ FromSample , Sample , SampleFormat } ;
use dasp_signal ::Signal ;
use tracing ::{ error , info , trace , warn } ;
use tokio ::sync ::mpsc ::Receiver ;
use crate ::task_msg ::{ PcmFrameMessage , PcmSampleMessage } ;
pub fn audio_transmitter_main (
mut rx_for_wire : Receiver < PcmSampleMessage > ,
cpal_output : cpal ::Device ,
) -> Result < ( ) > {
trace! ( " audio_transmitter started " ) ;
let cpal_output_config = cpal_output . supported_output_configs ( )
. context ( " could not find a suitable audio output configuration. are you root, trying to use a normal user's audio stack? try setting the capability CAP_NET_ADMIN=ep on this binary, and running as the user who is running the audio stack. " ) ?
. max_by_key ( | cfg | {
2024-12-16 11:44:14 -05:00
println! ( " AVAIL RATE: {:?} , {:?} , {:?} " , cfg . sample_format ( ) , cfg . min_sample_rate ( ) , cfg . max_sample_rate ( ) ) ;
2024-12-15 23:52:17 -05:00
match cfg . sample_format ( ) {
SampleFormat ::U8 = > 10 ,
SampleFormat ::I8 = > 11 ,
SampleFormat ::U16 = > 20 ,
SampleFormat ::I16 = > 21 ,
SampleFormat ::U32 = > 30 ,
SampleFormat ::I32 = > 31 ,
SampleFormat ::F32 = > 40 ,
SampleFormat ::F64 = > 50 ,
SampleFormat ::U64 = > 60 ,
SampleFormat ::I64 = > 61 ,
x = > { warn! ( " Backend offered unknown sample format {x} " , ) ; - 999 }
}
} ) . expect ( " output device has no supported configurations available " )
2024-12-16 11:44:14 -05:00
. with_sample_rate ( cpal ::SampleRate ( 384000 ) ) ; //max_sample_rate();
2024-12-15 23:52:17 -05:00
info! (
" output samples are {} @ {}hz " ,
& cpal_output_config . sample_format ( ) ,
& cpal_output_config . sample_rate ( ) . 0 ,
) ;
let failed_pcm_give = move | e | {
warn! ( " dropped some PCM data on output stream?! {} " , e ) ;
} ;
let mut i = 0 f64 ;
let output_stream = match cpal_output_config . sample_format ( ) {
cpal ::SampleFormat ::U8 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< u8 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I8 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< i8 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I16 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< i16 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I32 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< i32 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::F32 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< f32 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::F64 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< f64 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::U64 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< u64 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I64 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< i64 > ( pcm , & mut rx_for_wire , & mut i ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
sample_format = > Err ( anyhow ::Error ::msg ( format! (
" unsupported sample format '{}'! please ask developers to add it " ,
sample_format
) ) ) ? ,
} ;
output_stream
. play ( )
. context ( " failed to start ingive audio stream " ) ? ;
loop { }
Ok ( ( ) )
}
fn give_output_pcm < T > ( pcm : & mut [ T ] , channel : & mut Receiver < PcmSampleMessage > , i : & mut f64 )
where
T : Sample + std ::fmt ::Debug + FromSample < i64 > + FromSample < f64 > ,
{
2024-12-16 11:44:14 -05:00
print! ( " ALSA wanted {} samples... " , pcm . len ( ) ) ;
2024-12-15 23:52:17 -05:00
for outgoing in pcm . iter_mut ( ) {
* outgoing = match channel . try_recv ( ) {
Ok ( sample ) = > sample . to_sample ::< T > ( ) ,
2024-12-16 11:44:14 -05:00
Err ( _ ) = > ( std ::f64 ::consts ::PI * 2.0 * ( * i ) / ( 384000.0 / 100.0 ) ) . sin ( ) . to_sample ::< T > ( ) , //T::EQUILIBRIUM,
/* Err(_) => {
2024-12-15 23:52:17 -05:00
signal . next ( ) . to_sample ::< T > ( )
2024-12-16 11:44:14 -05:00
} * /
2024-12-15 23:52:17 -05:00
} ;
* i = * i % 384000.0 + 1.0 ;
//if *i > 200000.0 { break; }
}
2024-12-16 11:44:14 -05:00
println! ( " gave them " ) ;
2024-12-15 23:52:17 -05:00
//let mut ctr = 0usize;
}