From 3c79893217bc632c9b0efa815091bef3c779490c Mon Sep 17 00:00:00 2001 From: alexander Date: Fri, 26 Mar 2021 21:42:19 +0000 Subject: Opensource ML embedded evaluation kit Change-Id: I12e807f19f5cacad7cef82572b6dd48252fd61fd --- scripts/py/gen_audio_cpp.py | 153 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 scripts/py/gen_audio_cpp.py (limited to 'scripts/py/gen_audio_cpp.py') diff --git a/scripts/py/gen_audio_cpp.py b/scripts/py/gen_audio_cpp.py new file mode 100644 index 0000000..54fdb23 --- /dev/null +++ b/scripts/py/gen_audio_cpp.py @@ -0,0 +1,153 @@ +# Copyright (c) 2021 Arm Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Utility script to convert a set of audio clip in a given location into +corresponding cpp files and a single hpp file referencing the vectors +from the cpp files. +""" +import datetime +import glob +import math +import os + +import numpy as np +from os import path +from argparse import ArgumentParser +from jinja2 import Environment, FileSystemLoader +from gen_utils import AudioUtils + +parser = ArgumentParser() +parser.add_argument("--audio_path", type=str, help="path to audio folder to convert.") +parser.add_argument("--source_folder_path", type=str, help="path to source folder to be generated.") +parser.add_argument("--header_folder_path", type=str, help="path to header folder to be generated.") +parser.add_argument("--sampling_rate", type=int, help="target sampling rate.", default=16000) +parser.add_argument("--mono", type=bool, help="convert signal to mono.", default=True) +parser.add_argument("--offset", type=float, help="start reading after this time (in seconds).", default=0) +parser.add_argument("--duration", type=float, help="only load up to this much audio (in seconds).", default=0) +parser.add_argument("--res_type", type=AudioUtils.res_data_type, help=f"Resample type: {AudioUtils.res_type_list()}.", + default='kaiser_best') +parser.add_argument("--min_samples", type=int, help="Minimum sample number.", default=16000) +parser.add_argument("--license_template", type=str, help="Header template file", + default="header_template.txt") +parser.add_argument("-v", "--verbosity", action="store_true") +args = parser.parse_args() + +env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')), + trim_blocks=True, + lstrip_blocks=True) + + +def write_hpp_file(header_filepath, cc_filepath, header_template_file, num_audios, audio_filenames, audio_array_namesizes): + print(f"++ Generating {header_filepath}") + + header_template = env.get_template(header_template_file) + hdr = header_template.render(script_name=os.path.basename(__file__), + gen_time=datetime.datetime.now(), + year=datetime.datetime.now().year) + env.get_template('AudioClips.hpp.template').stream(common_template_header=hdr, + clips_count=num_audios, + varname_size=audio_array_namesizes + ) \ + .dump(str(header_filepath)) + + print(f"++ Generating {cc_filepath}") + + env.get_template('AudioClips.cc.template').stream(common_template_header=hdr, + clips_count=num_audios, + var_names=(name for name, _ in audio_array_namesizes), + clip_sizes=(size for _, size in audio_array_namesizes), + clip_names=audio_filenames) \ + .dump(str(cc_filepath)) + + +def write_individual_audio_cc_file(clip_dirpath, clip_filename, + cc_filename, header_template_file, array_name, + sampling_rate_value, mono_value, offset_value, + duration_value, res_type_value, min_len): + print(f"++ Converting {clip_filename} to {path.basename(cc_filename)}") + audio_filepath = path.join(clip_dirpath, clip_filename) + clip_data, samplerate = AudioUtils.load_resample_audio_clip(audio_filepath, + sampling_rate_value, mono_value, + offset_value, duration_value, + res_type_value, min_len) + + # Change from [-1, 1] fp32 range to int16 range. + clip_data = np.clip((clip_data * (1 << 15)), + np.iinfo(np.int16).min, + np.iinfo(np.int16).max).flatten().astype(np.int16) + + header_template = env.get_template(header_template_file) + hdr = header_template.render(script_name=os.path.basename(__file__), + gen_time=datetime.datetime.now(), + file_name=clip_filename, + year=datetime.datetime.now().year) + + hex_line_generator = (', '.join(map(hex, sub_arr)) + for sub_arr in np.array_split(clip_data, math.ceil(len(clip_data)/20))) + + env.get_template('audio.cc.template').stream(common_template_header=hdr, + size=len(clip_data), + var_name=array_name, + audio_data=hex_line_generator) \ + .dump(str(cc_filename)) + + return len(clip_data) + + +def main(args): + # Keep the count of the audio files converted + audioclip_idx = 0 + audioclip_filenames = [] + audioclip_array_names = [] + header_filename = "InputFiles.hpp" + common_cc_filename = "InputFiles.cc" + header_filepath = path.join(args.header_folder_path, header_filename) + common_cc_filepath = path.join(args.source_folder_path, common_cc_filename) + + if os.path.isdir(args.audio_path): + filepaths = sorted(glob.glob(path.join(args.audio_path, '**/*.wav'), recursive=True)) + elif os.path.isfile(args.audio_path): + filepaths = [args.audio_path] + else: + raise OSError("Directory or file does not exist.") + + for filepath in filepaths: + filename = path.basename(filepath) + clip_dirpath = path.dirname(filepath) + try: + audioclip_filenames.append(filename) + + # Save the cc file + cc_filename = path.join(args.source_folder_path, + (filename.rsplit(".")[0]).replace(" ", "_") + ".cc") + array_name = "audio" + str(audioclip_idx) + array_size = write_individual_audio_cc_file(clip_dirpath, filename, cc_filename, args.license_template, array_name, + args.sampling_rate, args.mono, args.offset, + args.duration, args.res_type, args.min_samples) + + audioclip_array_names.append((array_name, array_size)) + # Increment audio index + audioclip_idx = audioclip_idx + 1 + except: + if args.verbosity: + print(f"Failed to open {filename} as an audio.") + + write_hpp_file(header_filepath, common_cc_filepath, args.license_template, + audioclip_idx, audioclip_filenames, audioclip_array_names) + + +if __name__ == '__main__': + main(args) -- cgit v1.2.1