diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:17:30 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:17:46 +0100 |
commit | 13d7c09125f8eec703d0a43a9a87fc8aa08f7319 (patch) | |
tree | 70fd643c429cea5c1f9362c2674511d17a53f3b5 /Userland/Libraries/LibAudio/Buffer.cpp | |
parent | dc28c07fa526841e05e16161c74a6c23984f1dd5 (diff) | |
download | serenity-13d7c09125f8eec703d0a43a9a87fc8aa08f7319.zip |
Libraries: Move to Userland/Libraries/
Diffstat (limited to 'Userland/Libraries/LibAudio/Buffer.cpp')
-rw-r--r-- | Userland/Libraries/LibAudio/Buffer.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/Userland/Libraries/LibAudio/Buffer.cpp b/Userland/Libraries/LibAudio/Buffer.cpp new file mode 100644 index 0000000000..c23576482b --- /dev/null +++ b/Userland/Libraries/LibAudio/Buffer.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <LibAudio/Buffer.h> + +namespace Audio { + +template<typename SampleReader> +static void read_samples_from_stream(InputMemoryStream& stream, SampleReader read_sample, Vector<Sample>& samples, ResampleHelper& resampler, int num_channels) +{ + double norm_l = 0; + double norm_r = 0; + + switch (num_channels) { + case 1: + for (;;) { + while (resampler.read_sample(norm_l, norm_r)) { + samples.append(Sample(norm_l)); + } + norm_l = read_sample(stream); + + if (stream.handle_any_error()) { + break; + } + resampler.process_sample(norm_l, norm_r); + } + break; + case 2: + for (;;) { + while (resampler.read_sample(norm_l, norm_r)) { + samples.append(Sample(norm_l, norm_r)); + } + norm_l = read_sample(stream); + norm_r = read_sample(stream); + + if (stream.handle_any_error()) { + break; + } + resampler.process_sample(norm_l, norm_r); + } + break; + default: + ASSERT_NOT_REACHED(); + } +} + +static double read_norm_sample_24(InputMemoryStream& stream) +{ + u8 byte = 0; + stream >> byte; + u32 sample1 = byte; + stream >> byte; + u32 sample2 = byte; + stream >> byte; + u32 sample3 = byte; + + i32 value = 0; + value = sample1 << 8; + value |= (sample2 << 16); + value |= (sample3 << 24); + return double(value) / NumericLimits<i32>::max(); +} + +static double read_norm_sample_16(InputMemoryStream& stream) +{ + LittleEndian<i16> sample; + stream >> sample; + return double(sample) / NumericLimits<i16>::max(); +} + +static double read_norm_sample_8(InputMemoryStream& stream) +{ + u8 sample = 0; + stream >> sample; + return double(sample) / NumericLimits<u8>::max(); +} + +RefPtr<Buffer> Buffer::from_pcm_data(ReadonlyBytes data, ResampleHelper& resampler, int num_channels, int bits_per_sample) +{ + InputMemoryStream stream { data }; + return from_pcm_stream(stream, resampler, num_channels, bits_per_sample, data.size() / (bits_per_sample / 8)); +} + +RefPtr<Buffer> Buffer::from_pcm_stream(InputMemoryStream& stream, ResampleHelper& resampler, int num_channels, int bits_per_sample, int num_samples) +{ + Vector<Sample> fdata; + fdata.ensure_capacity(num_samples); + + switch (bits_per_sample) { + case 8: + read_samples_from_stream(stream, read_norm_sample_8, fdata, resampler, num_channels); + break; + case 16: + read_samples_from_stream(stream, read_norm_sample_16, fdata, resampler, num_channels); + break; + case 24: + read_samples_from_stream(stream, read_norm_sample_24, fdata, resampler, num_channels); + break; + default: + ASSERT_NOT_REACHED(); + } + + // We should handle this in a better way above, but for now -- + // just make sure we're good. Worst case we just write some 0s where they + // don't belong. + ASSERT(!stream.handle_any_error()); + + return Buffer::create_with_samples(move(fdata)); +} + +} |