Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
HighBlueParsers
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Paul Best
HighBlueParsers
Merge requests
!1
High blue rec
Code
Review changes
Check out branch
Download
Patches
Plain diff
Expand sidebar
Closed
High blue rec
pierre.mahe/highblueparsers:HighBlueRec
into
main
Overview
0
Commits
17
Pipelines
0
Changes
2
Closed
High blue rec
Pierre Mahe
requested to merge
pierre.mahe/highblueparsers:HighBlueRec
into
main
Oct 16, 2023
Overview
0
Commits
17
Pipelines
0
Changes
2
Increment version number
0
0
Merge request reports
Viewing commit
b5dee4eb
Prev
Next
Show latest version
2 files
+
10
−
1
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
2
b5dee4eb
Exit with an error if no audio data is received for a while
· b5dee4eb
Jan Schlüter
authored
Jun 18, 2019
src/main.cpp
0 → 100644
+
216
−
0
View file @ 72f85559
Edit in single-file editor
Open in Web IDE
/**
* SMIoT JASON Qualilife sound recorder command line program.
*
* Author: Jan Schlüter <jan.schluter@lis-lab.fr>
* Author: Maxence Ferrari <maxence.ferrari@lis-lab.fr>
*/
#include
<iostream>
#include
<string>
#include
<memory>
#include
<cstring>
#include
"recorder.h"
#include
"filewriter.h"
#include
"cleanexit.h"
void
print_usage
(
char
*
name
)
{
std
::
cout
<<
"SMIoT JASON Qualilife sound recorder"
;
#ifdef JASONREC_VERSION
std
::
cout
<<
" v"
<<
JASONREC_VERSION
;
#endif
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
"Usage: "
<<
name
<<
" channels rate filename [--help, -h] [--chunk_len, -c CHUNK_LEN] "
<<
"[--total_len, -t TOTAL_LEN] [--device, -d DEVICE] [--bit_depth, -b BIT_DEPTH] "
<<
"[--imu, -i IMU] [--filter, -f FILTER] [--verbose, -v]"
<<
std
::
endl
;
std
::
cout
<<
"Positional arguments:"
<<
std
::
endl
;
std
::
cout
<<
" CHANNELS:
\t
number of channels to record (1 to 5)"
<<
std
::
endl
;
std
::
cout
<<
" RATE:
\t
sample rate in Hz to record at (integral number)"
<<
std
::
endl
;
std
::
cout
<<
" FILENAME:
\t
output file name. should include strftime() format specifiers"
<<
std
::
endl
;
std
::
cout
<<
" if CHUNK_LEN is specified. For miliseconds, use %z. Example: location/recording_%Y%m%d_%H%M%S_%z.wav"
<<
std
::
endl
;
std
::
cout
<<
"Optional arguments:"
<<
std
::
endl
;
std
::
cout
<<
"-h, --help
\t\t
show this help message and exit"
<<
std
::
endl
;
std
::
cout
<<
" --bit_depth, -b
\t
BIT_DEPTH:
\t
Size of each samples in bits. Must be a multiple of 8. (Default: 16)"
<<
std
::
endl
;
std
::
cout
<<
" --imu, -i
\t
IMU:
\t
IMU file name. Similar to FILENAME. Disable by default."
<<
std
::
endl
;
std
::
cout
<<
" --filter, -f
\t
FILTER:
\t
Number of the filter to use. Must be between 0 and 2. (Default: 0)"
<<
std
::
endl
;
std
::
cout
<<
" --chunk_len, -c
\t
CHUNK_LEN:
\t
length per output file in seconds; will start a new file whenever"
<<
std
::
endl
;
std
::
cout
<<
" this length is reached. If not given or zero, will record a single file."
<<
std
::
endl
;
std
::
cout
<<
" --total_len, -t
\t
TOTAL_LEN:
\t
Total recording length; will stop when this length is reached."
<<
std
::
endl
;
std
::
cout
<<
" If not given or zero, will record continuously until killed."
<<
std
::
endl
;
std
::
cout
<<
" --device, -d
\t
DEVICE:
\t
Which device to use in case multiple JASON cards are connected,"
<<
std
::
endl
;
std
::
cout
<<
" where 0 is the first, 1 is the second card found (and so on)."
<<
std
::
endl
;
std
::
cout
<<
" --verbose, -v
\t\t
Enable the printing of status message "
<<
std
::
endl
;
}
int
record
(
size_t
channels
,
size_t
rate
,
size_t
depth
,
size_t
filter
,
std
::
string
&
filename
,
std
::
string
&
imu_name
,
float
chunklen
,
float
totallen
,
size_t
device
,
bool
verbose
)
{
JasonRecorder
recorder
=
JasonRecorder
(
verbose
);
std
::
cout
<<
"Found "
<<
recorder
.
get_device_count
()
<<
" JASON card(s)."
<<
std
::
endl
;
if
(
recorder
.
get_device_count
()
==
0
)
{
std
::
cout
<<
"Aborting."
<<
std
::
endl
;
return
2
;
}
try
{
// prepare the device
std
::
cout
<<
"Selecting device number "
<<
device
<<
"..."
<<
std
::
endl
;
recorder
.
set_device
(
device
);
// prepare the file writer
std
::
unique_ptr
<
FileWriter
>
filewriter
;
if
(
chunklen
>
0
&&
imu_name
.
empty
())
{
// implementation note: in C++14 we would use std::make_unique<SplitWavFileWriter>(...)
filewriter
.
reset
(
new
SplitWavFileWriter
(
filename
,
channels
,
rate
,
depth
,
chunklen
*
rate
));
}
else
if
(
chunklen
>
0
)
{
// implementation note: in C++14 we would use std::make_unique<SplitWavFileWriter>(...)
filewriter
.
reset
(
new
SplitIMUWavFileWriter
(
filename
,
imu_name
,
channels
,
rate
,
depth
,
chunklen
*
rate
));
}
else
if
(
imu_name
.
empty
()){
filewriter
.
reset
(
new
WavFileWriter
(
filename
,
channels
,
rate
,
depth
,
totallen
*
rate
));
}
else
{
filewriter
.
reset
(
new
SplitIMUWavFileWriter
(
filename
,
imu_name
,
channels
,
rate
,
depth
,
totallen
*
rate
));
}
// start the recording loop
std
::
cout
<<
"Starting to record..."
<<
std
::
endl
;
allow_clean_exit
();
size_t
total_samples_wanted
=
totallen
*
rate
;
size_t
total_samples_read
=
0
;
size_t
failed_attempts
=
0
;
size_t
sample_size
=
channels
*
depth
;
std
::
vector
<
std
::
uint8_t
>
samples
;
std
::
vector
<
std
::
uint8_t
>
imu_data
;
try
{
std
::
cout
<<
"Setting recording format to "
<<
channels
<<
" channels at "
<<
rate
<<
" Hz "
<<
(
8
*
depth
)
<<
" bits"
<<
std
::
endl
;
recorder
.
start_recording
(
channels
,
rate
,
depth
,
filter
);
// we will record until we have enough (or forever, if totallen == 0)
while
((
total_samples_wanted
==
0
)
||
(
total_samples_read
<
total_samples_wanted
))
{
if
(
exit_requested
())
{
std
::
cout
<<
"Termination requested."
<<
std
::
endl
;
break
;
}
recorder
.
get_samples
(
samples
,
imu_data
,
false
,
500
);
if
(
!
samples
.
empty
())
{
total_samples_read
+=
samples
.
size
()
/
sample_size
;
// if we have too much now, crop the last packet
if
((
total_samples_wanted
>
0
)
&&
(
total_samples_read
>
total_samples_wanted
))
{
samples
.
resize
(
samples
.
size
()
-
(
total_samples_read
-
total_samples_wanted
)
*
sample_size
);
}
// pass it on to the file writer
filewriter
->
write
(
samples
,
imu_data
);
failed_attempts
=
0
;
}
else
{
// if we received no message or no audio data 20x in a row, abort
failed_attempts
+=
1
;
if
(
failed_attempts
>=
20
)
{
throw
std
::
runtime_error
(
"Device does not send audio data."
);
}
}
}
recorder
.
stop_recording
();
std
::
cout
<<
"Stopped recording."
<<
std
::
endl
;
}
catch
(
const
std
::
exception
&
e
)
{
recorder
.
stop_recording
();
throw
;
}
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"Error: "
<<
e
.
what
()
<<
std
::
endl
;
return
2
;
}
return
0
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
if
(
argc
<
4
)
{
print_usage
(
argv
[
0
]);
return
2
;
}
// parse command line options
int
num_channels
;
try
{
num_channels
=
std
::
stoi
(
argv
[
1
]);
if
((
num_channels
<
1
)
||
(
num_channels
>
MAX_CHANNELS
))
{
std
::
cout
<<
"Error: CHANNELS must be in 1.."
<<
MAX_CHANNELS
<<
", got "
<<
num_channels
<<
" instead"
<<
std
::
endl
;
return
2
;}
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"Error: Could not interpret "
<<
argv
[
1
]
<<
" as an integer."
<<
std
::
endl
;
return
2
;
}
int
rate
;
try
{
rate
=
std
::
stoi
(
argv
[
2
]);
if
(
rate
!=
32000
&&
rate
!=
64000
&&
rate
!=
128000
&&
rate
!=
256000
&&
rate
!=
512000
)
{
std
::
cout
<<
"Error: RATE must be a power 2 times 32kHz, got "
<<
rate
<<
" instead"
<<
std
::
endl
;
return
2
;
}
}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"Error: Could not interpret "
<<
argv
[
2
]
<<
" as an integer."
<<
std
::
endl
;
return
2
;
}
std
::
string
filename
=
argv
[
3
];
int
i
=
4
;
int
device
(
0
),
bit_depth
(
16
),
filter
(
0
);
float
chunklen
(
0
),
totallen
(
0
);
std
::
string
imu_name
;
bool
verbose
(
false
);
while
(
i
<
argc
){
try
{
if
(
strcmp
(
argv
[
i
],
"--chunk_len"
)
==
0
||
strcmp
(
argv
[
i
],
"-c"
)
==
0
)
{
chunklen
=
atof
(
argv
[
++
i
]);
if
((
chunklen
<
0
))
{
std
::
cout
<<
"Error: CHUNKLEN must be positive or zero, got "
<<
chunklen
<<
" instead"
<<
std
::
endl
;
return
2
;
}}
else
if
(
strcmp
(
argv
[
i
],
"--imu"
)
==
0
||
strcmp
(
argv
[
i
],
"-i"
)
==
0
)
{
imu_name
=
argv
[
++
i
];
}
else
if
(
strcmp
(
argv
[
i
],
"--device"
)
==
0
||
strcmp
(
argv
[
i
],
"-d"
)
==
0
)
{
device
=
atoi
(
argv
[
++
i
]);
if
((
device
<
0
))
{
std
::
cout
<<
"Error: DEVICE must be nonnegative, got "
<<
device
<<
" instead"
<<
std
::
endl
;
return
2
;
}}
else
if
(
strcmp
(
argv
[
i
],
"--total_len"
)
==
0
||
strcmp
(
argv
[
i
],
"-t"
)
==
0
)
{
totallen
=
atof
(
argv
[
++
i
]);
if
((
totallen
<
0
))
{
std
::
cout
<<
"Error: TOTALLEN must be positive or zero, got "
<<
totallen
<<
" instead"
<<
std
::
endl
;
return
2
;
}}
else
if
(
strcmp
(
argv
[
i
],
"--bit_depth"
)
==
0
||
strcmp
(
argv
[
i
],
"-b"
)
==
0
)
{
bit_depth
=
atoi
(
argv
[
++
i
]);
if
(
bit_depth
%
8
)
{
std
::
cout
<<
"Error: DEPTH must be a multiple of 8, got "
<<
bit_depth
<<
" instead"
<<
std
::
endl
;
return
2
;
}}
else
if
(
strcmp
(
argv
[
i
],
"--filter"
)
==
0
||
strcmp
(
argv
[
i
],
"-f"
)
==
0
)
{
filter
=
atoi
(
argv
[
++
i
]);
if
(
filter
<
0
||
filter
>
2
)
{
std
::
cout
<<
"Error: filter must be between 0 and 2, got "
<<
filter
<<
" instead"
<<
std
::
endl
;
return
2
;
}}
else
if
(
strcmp
(
argv
[
i
],
"--help"
)
==
0
||
strcmp
(
argv
[
i
],
"-h"
)
==
0
){
print_usage
(
argv
[
0
]);
return
1
;
}
else
if
(
strcmp
(
argv
[
i
],
"--verbose"
)
==
0
||
strcmp
(
argv
[
i
],
"-v"
)
==
0
){
verbose
=
true
;
}
else
{
std
::
cout
<<
"Unrecognized argument "
<<
argv
[
i
]
<<
std
::
endl
;
return
2
;
}}
catch
(
const
std
::
exception
&
e
)
{
std
::
cout
<<
"Error: Could not interpret "
<<
argv
[
i
]
<<
" ( "
<<
argv
[
i
-
1
]
<<
" ) "
" as a number."
<<
std
::
endl
;
return
2
;
}
i
++
;
}
// hand over to the recording function
return
record
(
num_channels
,
rate
,
bit_depth
/
8
,
filter
,
filename
,
imu_name
,
chunklen
,
totallen
,
device
,
verbose
);
}
Loading