Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 1 | // |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 2 | // Copyright © 2021 Arm Ltd and Contributors. All rights reserved. |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 3 | // SPDX-License-Identifier: MIT |
| 4 | // |
| 5 | |
| 6 | #include "AudioCapture.hpp" |
| 7 | #include <alsa/asoundlib.h> |
| 8 | #include <sndfile.h> |
| 9 | #include <samplerate.h> |
| 10 | |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 11 | namespace audio |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 12 | { |
| 13 | std::vector<float> AudioCapture::LoadAudioFile(std::string filePath) |
| 14 | { |
| 15 | SF_INFO inputSoundFileInfo; |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 16 | SNDFILE* infile = nullptr; |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 17 | infile = sf_open(filePath.c_str(), SFM_READ, &inputSoundFileInfo); |
| 18 | |
| 19 | float audioIn[inputSoundFileInfo.channels * inputSoundFileInfo.frames]; |
| 20 | sf_read_float(infile, audioIn, inputSoundFileInfo.channels * inputSoundFileInfo.frames); |
| 21 | |
| 22 | float sampleRate = 16000.0f; |
| 23 | float srcRatio = sampleRate / (float)inputSoundFileInfo.samplerate; |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 24 | int outputFrames = ceilf(inputSoundFileInfo.frames * srcRatio); |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 25 | |
| 26 | // Convert to mono |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 27 | std::vector<float> monoData(inputSoundFileInfo.frames); |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 28 | for(int i = 0; i < inputSoundFileInfo.frames; i++) |
| 29 | { |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 30 | for(int j = 0; j < inputSoundFileInfo.channels; j++) |
| 31 | monoData[i] += audioIn[i * inputSoundFileInfo.channels + j]; |
| 32 | monoData[i] /= inputSoundFileInfo.channels; |
| 33 | } |
| 34 | |
| 35 | // Resample |
| 36 | SRC_DATA srcData; |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 37 | srcData.data_in = monoData.data(); |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 38 | srcData.input_frames = inputSoundFileInfo.frames; |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 39 | |
| 40 | std::vector<float> dataOut(outputFrames); |
| 41 | srcData.data_out = dataOut.data(); |
| 42 | |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 43 | srcData.output_frames = outputFrames; |
| 44 | srcData.src_ratio = srcRatio; |
| 45 | |
| 46 | src_simple(&srcData, SRC_SINC_BEST_QUALITY, 1); |
| 47 | |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 48 | sf_close(infile); |
| 49 | |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 50 | return dataOut; |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | void AudioCapture::InitSlidingWindow(float* data, size_t dataSize, int minSamples, size_t stride) |
| 54 | { |
| 55 | this->m_window = SlidingWindow<const float>(data, dataSize, minSamples, stride); |
| 56 | } |
| 57 | |
| 58 | bool AudioCapture::HasNext() |
| 59 | { |
| 60 | return m_window.HasNext(); |
| 61 | } |
| 62 | |
| 63 | std::vector<float> AudioCapture::Next() |
| 64 | { |
| 65 | if (this->m_window.HasNext()) |
| 66 | { |
| 67 | int remainingData = this->m_window.RemainingData(); |
| 68 | const float* windowData = this->m_window.Next(); |
| 69 | |
| 70 | size_t windowSize = this->m_window.GetWindowSize(); |
| 71 | |
| 72 | if(remainingData < windowSize) |
| 73 | { |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 74 | std::vector<float> audioData(windowSize, 0.0f); |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 75 | for(int i = 0; i < remainingData; ++i) |
| 76 | { |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 77 | audioData[i] = *windowData; |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 78 | if(i < remainingData - 1) |
| 79 | { |
| 80 | ++windowData; |
| 81 | } |
| 82 | } |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 83 | return audioData; |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 84 | } |
| 85 | else |
| 86 | { |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 87 | std::vector<float> audioData(windowData, windowData + windowSize); |
| 88 | return audioData; |
Éanna Ó Catháin | c6ab02a | 2021-04-07 14:35:25 +0100 | [diff] [blame] | 89 | } |
| 90 | } |
| 91 | else |
| 92 | { |
| 93 | throw std::out_of_range("Error, end of audio data reached."); |
| 94 | } |
| 95 | } |
George Gekov | 23c2627 | 2021-08-16 11:32:10 +0100 | [diff] [blame] | 96 | } //namespace asr |