Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Pierre Donat-Bouillud
audio-adaptive-scheduling
Commits
d667a217
Commit
d667a217
authored
Jun 14, 2019
by
Pierre Donat-Bouillud
Browse files
Formatting
parent
820b8448
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Cargo.lock
View file @
d667a217
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ansi_term"
version = "0.11.0"
...
...
benches/effect_benchmark.rs
View file @
d667a217
...
...
@@ -7,99 +7,127 @@ extern crate audio_adaptive;
extern
crate
rand
;
use
rand
::
prelude
::
*
;
use
rand
::
distributions
::
Uniform
;
use
rand
::
prelude
::
*
;
use
audio_adaptive
::
audiograph
::
*
;
use
audio_adaptive
::
samplerate
;
fn
osc_bench
(
c
:
&
mut
Criterion
)
{
fn
osc_bench
(
c
:
&
mut
Criterion
)
{
let
mut
rng
=
SmallRng
::
seed_from_u64
(
345987
);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
c
.bench_function_over_inputs
(
"osc"
,
move
|
b
:
&
mut
Bencher
,
n
:
&
usize
|
{
let
mut
osc
=
Oscillator
::
new
(
0.
,
440
,
1.
);
let
mut
input
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
//let size = input[0].buffer().len();
input
[
0
]
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
*
n
)
.collect
::
<
Vec
<
f32
>>
());
b
.iter
(
||
{
let
mut
output
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
osc
.process
(
&
input
,
&
mut
output
)}
)},
vec!
[
64
,
128
,
256
,
512
,
1024
,
2048
,
4096
]);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
c
.bench_function_over_inputs
(
"osc"
,
move
|
b
:
&
mut
Bencher
,
n
:
&
usize
|
{
let
mut
osc
=
Oscillator
::
new
(
0.
,
440
,
1.
);
let
mut
input
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
//let size = input[0].buffer().len();
input
[
0
]
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
*
n
)
.collect
::
<
Vec
<
f32
>>
(),
);
b
.iter
(||
{
let
mut
output
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
osc
.process
(
&
input
,
&
mut
output
)
})
},
vec!
[
64
,
128
,
256
,
512
,
1024
,
2048
,
4096
],
);
}
fn
mod_bench
(
c
:
&
mut
Criterion
)
{
fn
mod_bench
(
c
:
&
mut
Criterion
)
{
let
mut
rng
=
SmallRng
::
seed_from_u64
(
345987
);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
c
.bench_function_over_inputs
(
"mod"
,
move
|
b
:
&
mut
Bencher
,
n
:
&
usize
|
{
let
mut
modu
=
Modulator
::
new
(
0.
,
440
,
1.
);
let
mut
input
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
//let size = input[0].buffer().len();
input
[
0
]
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
*
n
)
.collect
::
<
Vec
<
f32
>>
());
b
.iter
(
||
{
let
mut
output
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
modu
.process
(
&
input
,
&
mut
output
)}
)},
vec!
[
64
,
128
,
256
,
512
,
1024
,
2048
,
4096
]);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
c
.bench_function_over_inputs
(
"mod"
,
move
|
b
:
&
mut
Bencher
,
n
:
&
usize
|
{
let
mut
modu
=
Modulator
::
new
(
0.
,
440
,
1.
);
let
mut
input
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
//let size = input[0].buffer().len();
input
[
0
]
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
*
n
)
.collect
::
<
Vec
<
f32
>>
(),
);
b
.iter
(||
{
let
mut
output
=
vec!
[
DspEdge
::
new
(
1
,
1
,
*
n
,
44100
);
1
];
modu
.process
(
&
input
,
&
mut
output
)
})
},
vec!
[
64
,
128
,
256
,
512
,
1024
,
2048
,
4096
],
);
}
fn
resampler_bench
(
c
:
&
mut
Criterion
)
{
let
parameters
=
vec!
[
samplerate
::
ConverterType
::
SincBestQuality
,
samplerate
::
ConverterType
::
SincMediumQuality
,
samplerate
::
ConverterType
::
SincFastest
,
samplerate
::
ConverterType
::
ZeroOrderHold
,
samplerate
::
ConverterType
::
Linear
];
fn
resampler_bench
(
c
:
&
mut
Criterion
)
{
let
parameters
=
vec!
[
samplerate
::
ConverterType
::
SincBestQuality
,
samplerate
::
ConverterType
::
SincMediumQuality
,
samplerate
::
ConverterType
::
SincFastest
,
samplerate
::
ConverterType
::
ZeroOrderHold
,
samplerate
::
ConverterType
::
Linear
,
];
let
mut
rng
=
SmallRng
::
seed_from_u64
(
345987
);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
c
.bench
(
"resampler"
,
ParameterizedBenchmark
::
new
(
"resampler"
,
move
|
b
,
conv_type
|
{
let
mut
conv
=
Resampler
::
new
(
conv_type
.clone
(),
0.5
);
let
mut
input
=
vec!
[
DspEdge
::
new
(
1
,
1
,
256
,
44100
);
1
];
let
mut
input
=
vec!
[
DspEdge
::
new
(
1
,
1
,
256
,
44100
);
1
];
let
size
=
input
[
0
]
.buffer
()
.len
();
input
[
0
]
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
size
)
.collect
::
<
Vec
<
f32
>>
());
input
[
0
]
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
size
)
.collect
::
<
Vec
<
f32
>>
(),
);
b
.iter
(||
{
let
mut
output
=
vec!
[
DspEdge
::
new
(
1
,
1
,
128
,
44100
);
1
];
let
mut
output
=
vec!
[
DspEdge
::
new
(
1
,
1
,
128
,
44100
);
1
];
conv
.process
(
&
input
,
&
mut
output
)
})},
parameters
)
})
},
parameters
,
),
);
}
fn
mixer_bench
(
c
:
&
mut
Criterion
)
{
fn
mixer_bench
(
c
:
&
mut
Criterion
)
{
let
n
=
6
;
let
mut
parameters
=
Vec
::
with_capacity
(
n
*
n
);
let
mut
parameters
=
Vec
::
with_capacity
(
n
*
n
);
for
i
in
1
..
n
{
for
j
in
1
..
n
{
if
i
%
j
==
0
||
j
%
i
==
0
{
parameters
.push
((
j
,
i
));}
if
i
%
j
==
0
||
j
%
i
==
0
{
parameters
.push
((
j
,
i
));
}
}
}
let
mut
rng
=
SmallRng
::
seed_from_u64
(
345987
);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
let
unity_interval
=
Uniform
::
new_inclusive
(
-
1.
,
1.
);
c
.bench
(
"mixer"
,
ParameterizedBenchmark
::
new
(
"mixer"
,
move
|
b
,
(
nb_inlets
,
nb_outlets
)|
{
let
mut
conv
=
InputsOutputsAdaptor
::
new
(
*
nb_inlets
,
*
nb_outlets
);
let
mut
inputs
=
vec!
[
DspEdge
::
new
(
1
,
1
,
256
,
44100
);
*
nb_inlets
];
let
mut
inputs
=
vec!
[
DspEdge
::
new
(
1
,
1
,
256
,
44100
);
*
nb_inlets
];
let
size
=
inputs
[
0
]
.buffer
()
.len
();
for
input
in
inputs
.iter_mut
()
{
input
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
size
)
.collect
::
<
Vec
<
f32
>>
());
input
.buffer_mut
()
.copy_from_slice
(
&
rng
.sample_iter
(
&
unity_interval
)
.take
(
size
)
.collect
::
<
Vec
<
f32
>>
(),
);
}
b
.iter
(||
{
let
mut
outputs
=
vec!
[
DspEdge
::
new
(
1
,
1
,
256
,
44100
);
*
nb_outlets
];
let
mut
outputs
=
vec!
[
DspEdge
::
new
(
1
,
1
,
256
,
44100
);
*
nb_outlets
];
conv
.process
(
&
inputs
,
&
mut
outputs
)
})},
parameters
)
})
},
parameters
,
),
);
}
criterion_group!
(
benches
,
osc_bench
,
mod_bench
,
resampler_bench
,
mixer_bench
);
criterion_main!
(
benches
);
src/audioengine.rs
View file @
d667a217
//! ALl the stuff related to audio, audio callback, portaudio, monitoring the callback
use
portaudio
as
pa
;
use
std
::
sync
::
mpsc
;
use
std
::
error
::
Error
;
use
time
::{
PreciseTime
,
Duration
};
use
std
::
path
::
Path
;
use
std
::
sync
::
mpsc
;
use
std
::
thread
;
use
time
::{
Duration
,
PreciseTime
};
use
audio_adaptive
::
sndfile
::
*
;
use
audio_adaptive
::
samplerate
::
*
;
use
audio_adaptive
::
sndfile
::
*
;
use
std
::
io
::
prelude
::
*
;
use
std
::
fs
::
File
;
use
std
::
io
::
prelude
::
*
;
use
std
;
const
FRAMES_PER_BUFFER
:
u32
=
64
;
const
UP_RATIO
:
f64
=
2.
;
const
FRAMES_PER_BUFFER
:
u32
=
64
;
const
UP_RATIO
:
f64
=
2.
;
lazy_static!
{
static
ref
PORTAUDIO
:
pa
::
PortAudio
=
{
let
pa
=
pa
::
PortAudio
::
new
()
.expect
(
"PortAudio construction shouldn't fail."
);
let
pa
=
pa
::
PortAudio
::
new
()
.expect
(
"PortAudio construction shouldn't fail."
);
println!
(
"PortAudio is initialized."
);
pa
};
}
#[derive(Debug)]
struct
TimeMonitoring
{
pub
current_invocation
:
f64
,
//When the audio callback is invoked (in s)
pub
buffer_dac
:
f64
,
// when the first sample of the output buffer will be send to the DAC (in s)
pub
audio_processing
:
Duration
,
//duration between beginning of callback and when the audio processing has been finished in the audio callback
pub
ratio
:
f64
,
//Resampling ratio
pub
current_invocation
:
f64
,
//When the audio callback is invoked (in s)
pub
buffer_dac
:
f64
,
// when the first sample of the output buffer will be send to the DAC (in s)
pub
audio_processing
:
Duration
,
//duration between beginning of callback and when the audio processing has been finished in the audio callback
pub
ratio
:
f64
,
//Resampling ratio
}
pub
struct
AudioEngine
{
pub
stream
:
pa
::
stream
::
Stream
<
pa
::
stream
::
NonBlocking
,
pa
::
stream
::
Output
<
f32
>>
,
pub
control_sender
:
mpsc
::
Sender
<
f64
>
,
pub
struct
AudioEngine
{
pub
stream
:
pa
::
stream
::
Stream
<
pa
::
stream
::
NonBlocking
,
pa
::
stream
::
Output
<
f32
>>
,
pub
control_sender
:
mpsc
::
Sender
<
f64
>
,
}
impl
AudioEngine
{
pub
fn
new
<
T
:
AsRef
<
Path
>
>
(
path
:
T
)
->
Result
<
AudioEngine
,
pa
::
Error
>
{
pub
fn
new
<
T
:
AsRef
<
Path
>>
(
path
:
T
)
->
Result
<
AudioEngine
,
pa
::
Error
>
{
/*
* Load samples
*/
...
...
@@ -58,74 +52,107 @@ impl AudioEngine {
let
audiostream
=
sndfile
.readf_float_all
();
println!
(
"Simple test of sound nodes with tradeoff between quality and deadlines."
);
println!
(
"Number of samples x number of channels = {}"
,
audiostream
.len
());
println!
(
"Number of samples x number of channels = {}"
,
audiostream
.len
()
);
/*
* Playback with portaudio
*/
//Thread to monitor the audio callback
let
(
tx_monit_exec
,
rx_monit_exec
)
=
mpsc
::
channel
::
<
TimeMonitoring
>
();
//Thread to monitor the audio callback
let
(
tx_monit_exec
,
rx_monit_exec
)
=
mpsc
::
channel
::
<
TimeMonitoring
>
();
thread
::
spawn
(
move
||
{
let
mut
f
=
File
::
create
(
"execution_audio"
)
.expect
(
"Impossible to report execution times"
);
thread
::
spawn
(
move
||
{
let
mut
f
=
File
::
create
(
"execution_audio"
)
.expect
(
"Impossible to report execution times"
);
f
.write_all
(
b"CurrentInvocation
\t
BufferDac
\t
AudioProcNS
\t
Ratio
\n
"
)
.unwrap
();
f
.write_all
(
b"CurrentInvocation
\t
BufferDac
\t
AudioProcNS
\t
Ratio
\n
"
)
.unwrap
();
for
monitoring_infos
in
rx_monit_exec
.iter
()
{
let
duration
:
Duration
=
monitoring_infos
.audio_processing
;
let
seria
=
format!
(
"{}
\t
{}
\t
{}
\t
{}
\n
"
,
monitoring_infos
.current_invocation
,
monitoring_infos
.buffer_dac
,
duration
.num_nanoseconds
()
.unwrap
(),
monitoring_infos
.ratio
);
f
.write_all
(
seria
.as_bytes
())
.unwrap
();
let
duration
:
Duration
=
monitoring_infos
.audio_processing
;
let
seria
=
format!
(
"{}
\t
{}
\t
{}
\t
{}
\n
"
,
monitoring_infos
.current_invocation
,
monitoring_infos
.buffer_dac
,
duration
.num_nanoseconds
()
.unwrap
(),
monitoring_infos
.ratio
);
f
.write_all
(
seria
.as_bytes
())
.unwrap
();
}
println!
(
"End monitoring execution times because {:?}"
,
rx_monit_exec
.recv
()
.unwrap_err
()
.description
());
});
//Audio callback and audio callback communication
let
(
tx
,
rx
)
=
mpsc
::
channel
();
let
mut
up_ratio
=
UP_RATIO
;
let
mut
chunk_it
=
0
;
//Resampling apparatus...
let
mut
nb_samples_interm
=
nb_channels
as
usize
*
FRAMES_PER_BUFFER
as
usize
*
up_ratio
as
usize
;
let
mut
upsampler
=
SmartResampler
::
new
(
ConverterType
::
Linear
,
nb_channels
as
u32
,
up_ratio
,
nb_samples_interm
*
20
);
let
mut
downsampler
=
SmartResampler
::
new
(
ConverterType
::
Linear
,
nb_channels
as
u32
,
1.
/
up_ratio
,
nb_samples_interm
*
10
);
let
mut
interm_buffer
=
vec!
[
0.
;
nb_samples_interm
];
interm_buffer
.reserve
(
nb_channels
as
usize
*
FRAMES_PER_BUFFER
as
usize
*
std
::
cmp
::
max
(
20
,
UP_RATIO
as
usize
));
let
callback
=
move
|
pa
::
OutputStreamCallbackArgs
{
buffer
,
frames
,
time
,
..
}|
{
let
start
=
PreciseTime
::
now
();
while
let
Ok
(
val
)
=
rx
.try_recv
()
{
up_ratio
=
val
;
}
//New ratio so resize buffer and change resampling ratios
nb_samples_interm
=
(
nb_channels
as
f64
*
FRAMES_PER_BUFFER
as
f64
*
up_ratio
)
.ceil
()
as
usize
;
//println!("New interm buffer size: {}", nb_samples_interm);
interm_buffer
.resize
(
nb_samples_interm
,
0.
);
//It shoudn't reallocate memory as we have reserved enough before starting the audio thread
upsampler
.set_src_ratio
(
up_ratio
);
downsampler
.set_src_ratio_hard
(
1.
/
up_ratio
);
//The problem with set_src_ratio is that it is going to try to transition smoothly to the
// new ratio, not yielding the righ number of samples.
let
nb_samples
=
frames
*
nb_channels
;
/*
* frame of size 3 with 3 channels. Nb samples is 9
* ||ch1|ch2|ch3||ch1|ch2|ch3||ch1|ch2|ch3||
*/
if
chunk_it
<
audiostream
.len
()
{
let
input_buffer
=
&
audiostream
[
chunk_it
..
std
::
cmp
::
min
(
chunk_it
+
nb_samples
,
audiostream
.len
())];
println!
(
"End monitoring execution times because {:?}"
,
rx_monit_exec
.recv
()
.unwrap_err
()
.description
()
);
});
//Audio callback and audio callback communication
let
(
tx
,
rx
)
=
mpsc
::
channel
();
let
mut
up_ratio
=
UP_RATIO
;
let
mut
chunk_it
=
0
;
//Resampling apparatus...
let
mut
nb_samples_interm
=
nb_channels
as
usize
*
FRAMES_PER_BUFFER
as
usize
*
up_ratio
as
usize
;
let
mut
upsampler
=
SmartResampler
::
new
(
ConverterType
::
Linear
,
nb_channels
as
u32
,
up_ratio
,
nb_samples_interm
*
20
,
);
let
mut
downsampler
=
SmartResampler
::
new
(
ConverterType
::
Linear
,
nb_channels
as
u32
,
1.
/
up_ratio
,
nb_samples_interm
*
10
,
);
let
mut
interm_buffer
=
vec!
[
0.
;
nb_samples_interm
];
interm_buffer
.reserve
(
nb_channels
as
usize
*
FRAMES_PER_BUFFER
as
usize
*
std
::
cmp
::
max
(
20
,
UP_RATIO
as
usize
),
);
let
callback
=
move
|
pa
::
OutputStreamCallbackArgs
{
buffer
,
frames
,
time
,
..
}|
{
let
start
=
PreciseTime
::
now
();
while
let
Ok
(
val
)
=
rx
.try_recv
()
{
up_ratio
=
val
;
}
//New ratio so resize buffer and change resampling ratios
nb_samples_interm
=
(
nb_channels
as
f64
*
FRAMES_PER_BUFFER
as
f64
*
up_ratio
)
.ceil
()
as
usize
;
//println!("New interm buffer size: {}", nb_samples_interm);
interm_buffer
.resize
(
nb_samples_interm
,
0.
);
//It shoudn't reallocate memory as we have reserved enough before starting the audio thread
upsampler
.set_src_ratio
(
up_ratio
);
downsampler
.set_src_ratio_hard
(
1.
/
up_ratio
);
//The problem with set_src_ratio is that it is going to try to transition smoothly to the
// new ratio, not yielding the righ number of samples.
let
nb_samples
=
frames
*
nb_channels
;
/*
* frame of size 3 with 3 channels. Nb samples is 9
* ||ch1|ch2|ch3||ch1|ch2|ch3||ch1|ch2|ch3||
*/
if
chunk_it
<
audiostream
.len
()
{
let
input_buffer
=
&
audiostream
[
chunk_it
..
std
::
cmp
::
min
(
chunk_it
+
nb_samples
,
audiostream
.len
())];
//chunk_it+ nb_samples = audiostream.len() at the end, normally (TODO: to check)
//upsample
upsampler
.resample
(
input_buffer
,
&
mut
interm_buffer
[
..
])
.unwrap
();
upsampler
.resample
(
input_buffer
,
&
mut
interm_buffer
[
..
])
.unwrap
();
//Do some processing
//buffer.clone_from_slice(&audiostream[chunk_it..std::cmp::min(chunk_it+ nb_samples, audiostream.len())]);
...
...
@@ -135,39 +162,51 @@ impl AudioEngine {
//
//downsample
downsampler
.resample
(
&
interm_buffer
[
..
],
&
mut
buffer
[
..
])
.unwrap
();
downsampler
.resample
(
&
interm_buffer
[
..
],
&
mut
buffer
[
..
])
.unwrap
();
//Send monitoring infos
let
duration
=
start
.to
(
PreciseTime
::
now
());
tx_monit_exec
.send
(
TimeMonitoring
{
current_invocation
:
time
.current
,
buffer_dac
:
time
.buffer_dac
,
audio_processing
:
duration
,
ratio
:
up_ratio
,
})
.unwrap
();
tx_monit_exec
.send
(
TimeMonitoring
{
current_invocation
:
time
.current
,
buffer_dac
:
time
.buffer_dac
,
audio_processing
:
duration
,
ratio
:
up_ratio
,
})
.unwrap
();
chunk_it
+=
nb_samples
;
pa
::
Continue
}
else
{
}
else
{
upsampler
.next_buffer_last
();
pa
::
Complete
}
};
//Init portaudio and stream
//Show default API:
println!
(
"{:?}"
,
PORTAUDIO
.host_api_info
(
PORTAUDIO
.default_host_api
()
.unwrap
())
.unwrap
());
let
settings
=
try
!
(
PORTAUDIO
.default_output_stream_settings
(
nb_channels
as
i32
,
samplerate
,
nb_frames
));
let
mut
stream
=
try
!
(
PORTAUDIO
.open_non_blocking_stream
(
settings
,
callback
));
try
!
(
stream
.start
());
Ok
(
AudioEngine
{
stream
:
stream
,
control_sender
:
tx
,
})
};
//Init portaudio and stream
//Show default API:
println!
(
"{:?}"
,
PORTAUDIO
.host_api_info
(
PORTAUDIO
.default_host_api
()
.unwrap
())
.unwrap
()
);
let
settings
=
try
!
(
PORTAUDIO
.default_output_stream_settings
(
nb_channels
as
i32
,
samplerate
,
nb_frames
));
let
mut
stream
=
try
!
(
PORTAUDIO
.open_non_blocking_stream
(
settings
,
callback
));
try
!
(
stream
.start
());
Ok
(
AudioEngine
{
stream
:
stream
,
control_sender
:
tx
,
})
}
}
...
...
src/audiograph.rs
View file @
d667a217
This diff is collapsed.
Click to expand it.
src/audiograph_exec.rs
View file @
d667a217
//! Execute an audiograph file and report stats about it.
extern
crate
audio_adaptive
;
extern
crate
clap
;
extern
crate
crossbeam_channel
;
extern
crate
portaudio
;
extern
crate
rand
;
extern
crate
time
;
extern
crate
crossbeam_channel
;
extern
crate
clap
;
use
portaudio
as
pa
;
use
crossbeam_channel
::
unbounded
;
use
portaudio
as
pa
;
use
std
::
env
;
use
std
::
thread
;
use
std
::
time
as
rust_time
;
//To be used for thread::sleep for instance
use
std
::
process
::
exit
;
use
std
::
thread
;
use
std
::
time
as
rust_time
;
//To be used for thread::sleep for instance
use
time
::{
PreciseTime
,
Duration
};
use
time
::{
Duration
,
PreciseTime
};
use
std
::
io
::
prelude
::
*
;
use
std
::
ffi
::
OsStr
;
use
std
::
fs
::
File
;
use
std
::
io
::
prelude
::
*
;
use
std
::
path
::
Path
;
use
std
::
ffi
::
OsStr
;
use
clap
::{
A
rg
,
A
pp
,
ArgGroup
};
use
clap
::{
A
pp
,
A
rg
,
ArgGroup
};
use
audio_adaptive
::
audiograph
::
*
;
use
audio_adaptive
::
audiograph_parser
::
*
;
use
audio_adaptive
::
sndfile
;
use
rand
::
prelude
::
*
;
use
rand
::
distributions
::
Uniform
;
use
rand
::
prelude
::
*
;
const
CHANNELS
:
i32
=
1
;
const
SAMPLE_RATE
:
u32
=
44_100
;
const
NB_CYCLES
:
u32
=
12000
;
const
FRAMES_PER_BUFFER
:
usize
=
512
;
const
NB_CYCLES
:
u32
=
12000
;
const
FRAMES_PER_BUFFER
:
usize
=
512
;
#[derive(Clone,
Copy,
Debug)]
pub
struct
TimeMonitor
{
/// Time budget remaining at the end (if negative, deadline exceeded)
pub
budget
:
i64
,
pub
budget
:
i64
,
/// Deadline as given by portaudio
pub
deadline
:
u64
,
pub
deadline
:
u64
,
/// Execution time for one cycle
pub
execution_time
:
i64
,
pub
callback_flags
:
audio_adaptive
::
effect
::
CallbackFlags
,
pub
execution_time
:
i64
,
pub
callback_flags
:
audio_adaptive
::
effect
::
CallbackFlags
,
}
impl
Default
for
TimeMonitor
{
fn
default
()
->
Self
{
TimeMonitor
{
budget
:
0
,
deadline
:
0
,
execution_time
:
0
,
callback_flags
:
audio_adaptive
::
effect
::
CallbackFlags
::
NO_FLAG
}
}
fn
default
()
->
Self
{
TimeMonitor
{
budget
:
0
,
deadline
:
0
,
execution_time
:
0
,
callback_flags
:
audio_adaptive
::
effect
::
CallbackFlags
::
NO_FLAG
,
}
}
}
//Launch a audio graph in real time
fn
real_time_run
(
mut
audio_graph
:
AudioGraph
,
graph_name
:
String
,
cycles
:
u32
,
monitor
:
bool
)
->
Result
<
(),
pa
::
Error
>
{
fn
real_time_run
(
mut
audio_graph
:
AudioGraph
,
graph_name
:
String
,
cycles
:
u32
,
monitor
:
bool
,
)
->
Result
<
(),
pa
::
Error
>
{
let
pa
=
try
!
(
pa
::
PortAudio
::
new
());
//audio_graph.update_schedule().expect("Cycle detected");//Already done when parsing
...
...
@@ -64,8 +73,11 @@ fn real_time_run(mut audio_graph: AudioGraph, graph_name: String, cycles: u32, m
let
buffer_size
=
audio_graph
.frames_per_buffer
()
*
audio_graph
.nb_channels
();
let
settings
=
try
!
(
pa
.default_output_stream_settings
(
audio_graph
.nb_channels
()
as
i32
,
SAMPLE_RATE
as
f64
,
buffer_size
));
let
settings
=
try
!
(
pa
.default_output_stream_settings
(
audio_graph
.nb_channels
()
as
i32
,
SAMPLE_RATE
as
f64
,
buffer_size
));
let
mut
nb_cycles
=
0
;
...
...
@@ -74,15 +86,20 @@ fn real_time_run(mut audio_graph: AudioGraph, graph_name: String, cycles: u32, m
thread
::
spawn
(
move
||
{
if
monitor
{
let
mut
f
=
File
::
create
(
format!
(
"{}_{}-rt.csv"
,
time
::
now
()
.rfc3339
(),
graph_name
))
.expect
(
"Impossible to report execution times"
);
f
.write_all
(
format!
(
"{} {}
\n
"
,
nb_nodes
,
nb_edges
)
.as_bytes
())
.unwrap
();