Downscaling working!
This commit is contained in:
@@ -297,7 +297,8 @@ auto AudioTask::FinishDecoding(InputStream& stream) -> void {
|
|||||||
InputStream padded_stream{mad_buffer.get()};
|
InputStream padded_stream{mad_buffer.get()};
|
||||||
|
|
||||||
OutputStream writer{codec_buffer_.get()};
|
OutputStream writer{codec_buffer_.get()};
|
||||||
auto res = codec_->ContinueStream(stream.data(), writer.data_as<sample::Sample>());
|
auto res =
|
||||||
|
codec_->ContinueStream(stream.data(), writer.data_as<sample::Sample>());
|
||||||
if (res.second.has_error()) {
|
if (res.second.has_error()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,19 +117,19 @@ auto I2SAudioOutput::AdjustVolumeDown() -> bool {
|
|||||||
|
|
||||||
auto I2SAudioOutput::PrepareFormat(const StreamInfo::Pcm& orig)
|
auto I2SAudioOutput::PrepareFormat(const StreamInfo::Pcm& orig)
|
||||||
-> StreamInfo::Pcm {
|
-> StreamInfo::Pcm {
|
||||||
return StreamInfo::Pcm{
|
/*
|
||||||
|
return StreamInfo::Pcm{
|
||||||
.channels = std::min<uint8_t>(orig.channels, 2),
|
.channels = std::min<uint8_t>(orig.channels, 2),
|
||||||
.bits_per_sample = std::clamp<uint8_t>(orig.bits_per_sample, 16, 32),
|
.bits_per_sample = std::clamp<uint8_t>(orig.bits_per_sample, 16, 32),
|
||||||
.sample_rate = std::clamp<uint32_t>(orig.sample_rate, 8000, 96000),
|
.sample_rate = std::clamp<uint32_t>(orig.sample_rate, 8000, 96000),
|
||||||
};
|
};
|
||||||
/*
|
*/
|
||||||
return StreamInfo::Pcm{
|
return StreamInfo::Pcm{
|
||||||
.channels = std::min<uint8_t>(orig.channels, 2),
|
.channels = std::min<uint8_t>(orig.channels, 2),
|
||||||
.bits_per_sample = 16,
|
.bits_per_sample = 16,
|
||||||
//.sample_rate = std::clamp<uint32_t>(orig.sample_rate, 8000, 96000),
|
//.sample_rate = std::clamp<uint32_t>(orig.sample_rate, 8000, 96000),
|
||||||
.sample_rate = 32000,
|
.sample_rate = 44100,
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto I2SAudioOutput::Configure(const StreamInfo::Pcm& pcm) -> void {
|
auto I2SAudioOutput::Configure(const StreamInfo::Pcm& pcm) -> void {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class Resampler {
|
|||||||
|
|
||||||
auto Process(cpp::span<const sample::Sample> input,
|
auto Process(cpp::span<const sample::Sample> input,
|
||||||
cpp::span<sample::Sample> output,
|
cpp::span<sample::Sample> output,
|
||||||
bool end_of_data) -> std::pair<size_t,size_t>;
|
bool end_of_data) -> std::pair<size_t, size_t>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto Subsample(int channel) -> float;
|
auto Subsample(int channel) -> float;
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ class SinkMixer {
|
|||||||
auto HandleBytes() -> void;
|
auto HandleBytes() -> void;
|
||||||
|
|
||||||
auto Resample(InputStream&, OutputStream&) -> bool;
|
auto Resample(InputStream&, OutputStream&) -> bool;
|
||||||
auto ApplyDither(cpp::span<sample::Sample> samples, uint_fast8_t bits) -> void;
|
auto ApplyDither(cpp::span<sample::Sample> samples, uint_fast8_t bits)
|
||||||
|
-> void;
|
||||||
auto Downscale(cpp::span<sample::Sample>, cpp::span<int16_t>) -> void;
|
auto Downscale(cpp::span<sample::Sample>, cpp::span<int16_t>) -> void;
|
||||||
|
|
||||||
enum class Command {
|
enum class Command {
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ auto SinkMixer::HandleBytes() -> void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!input_stream_->empty()) {
|
while (input_stream_->info().bytes_in_stream() >= sizeof(sample::Sample)) {
|
||||||
RawStream* output_source;
|
RawStream* output_source;
|
||||||
if (pcm->sample_rate != target_format_.sample_rate) {
|
if (pcm->sample_rate != target_format_.sample_rate) {
|
||||||
OutputStream resampled_writer{resampled_stream_.get()};
|
OutputStream resampled_writer{resampled_stream_.get()};
|
||||||
@@ -150,6 +150,9 @@ auto SinkMixer::HandleBytes() -> void {
|
|||||||
output_source = input_stream_.get();
|
output_source = input_stream_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t bytes_consumed = output_source->info().bytes_in_stream();
|
||||||
|
size_t bytes_to_send = output_source->info().bytes_in_stream();
|
||||||
|
|
||||||
if (target_format_.bits_per_sample == 16) {
|
if (target_format_.bits_per_sample == 16) {
|
||||||
// This is slightly scary; we're basically reaching into the internals of
|
// This is slightly scary; we're basically reaching into the internals of
|
||||||
// the stream buffer to do in-place conversion of samples. Saving an
|
// the stream buffer to do in-place conversion of samples. Saving an
|
||||||
@@ -163,19 +166,20 @@ auto SinkMixer::HandleBytes() -> void {
|
|||||||
ApplyDither(src, 16);
|
ApplyDither(src, 16);
|
||||||
Downscale(src, dest);
|
Downscale(src, dest);
|
||||||
|
|
||||||
output_source->info().bytes_in_stream() = dest.size_bytes();
|
bytes_consumed = src.size_bytes();
|
||||||
|
bytes_to_send = src.size_bytes() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream output{output_source};
|
InputStream output{output_source};
|
||||||
cpp::span<const std::byte> buf = output.data();
|
cpp::span<const std::byte> buf = output.data();
|
||||||
|
|
||||||
size_t bytes_sent = 0;
|
size_t bytes_sent = 0;
|
||||||
while (bytes_sent < buf.size_bytes()) {
|
while (bytes_sent < bytes_to_send) {
|
||||||
auto cropped = buf.subspan(bytes_sent);
|
auto cropped = buf.subspan(bytes_sent, bytes_to_send - bytes_sent);
|
||||||
bytes_sent += xStreamBufferSend(sink_, cropped.data(),
|
bytes_sent += xStreamBufferSend(sink_, cropped.data(),
|
||||||
cropped.size_bytes(), portMAX_DELAY);
|
cropped.size_bytes(), portMAX_DELAY);
|
||||||
}
|
}
|
||||||
output.consume(bytes_sent);
|
output.consume(bytes_consumed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ RawStream::RawStream(std::size_t size)
|
|||||||
RawStream::RawStream(std::size_t size, uint32_t caps)
|
RawStream::RawStream(std::size_t size, uint32_t caps)
|
||||||
: info_(),
|
: info_(),
|
||||||
buffer_size_(size),
|
buffer_size_(size),
|
||||||
buffer_(reinterpret_cast<std::byte*>(
|
buffer_(reinterpret_cast<std::byte*>(heap_caps_malloc(size, caps))) {
|
||||||
heap_caps_malloc(size, caps))) {
|
|
||||||
assert(buffer_ != NULL);
|
assert(buffer_ != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "sample.hpp"
|
|
||||||
#include "result.hpp"
|
#include "result.hpp"
|
||||||
|
#include "sample.hpp"
|
||||||
#include "span.hpp"
|
#include "span.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -269,7 +269,6 @@ void foconv(int* src, uint8_t* dst, int bits, int skip, int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace sample
|
||||||
|
|
||||||
}
|
} // namespace audio
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
+5
-4
@@ -59,13 +59,14 @@ template <Type t>
|
|||||||
auto StartPersistent(const std::function<void(void)>& fn) -> void {
|
auto StartPersistent(const std::function<void(void)>& fn) -> void {
|
||||||
StaticTask_t* task_buffer = new StaticTask_t;
|
StaticTask_t* task_buffer = new StaticTask_t;
|
||||||
cpp::span<StackType_t> stack = AllocateStack<t>();
|
cpp::span<StackType_t> stack = AllocateStack<t>();
|
||||||
xTaskCreateStatic(&PersistentMain, Name<t>().c_str(),
|
xTaskCreateStatic(&PersistentMain, Name<t>().c_str(), stack.size(),
|
||||||
stack.size(), new std::function<void(void)>(fn),
|
new std::function<void(void)>(fn), Priority<t>(),
|
||||||
Priority<t>(), stack.data(), task_buffer);
|
stack.data(), task_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Type t>
|
template <Type t>
|
||||||
auto StartPersistent(BaseType_t core, const std::function<void(void)>& fn) -> void {
|
auto StartPersistent(BaseType_t core, const std::function<void(void)>& fn)
|
||||||
|
-> void {
|
||||||
StaticTask_t* task_buffer = new StaticTask_t;
|
StaticTask_t* task_buffer = new StaticTask_t;
|
||||||
cpp::span<StackType_t> stack = AllocateStack<t>();
|
cpp::span<StackType_t> stack = AllocateStack<t>();
|
||||||
xTaskCreateStaticPinnedToCore(&PersistentMain, Name<t>().c_str(),
|
xTaskCreateStaticPinnedToCore(&PersistentMain, Name<t>().c_str(),
|
||||||
|
|||||||
Reference in New Issue
Block a user