新增sample_t和USE_DOUBLE_SAMPLE, 用于双精度渲染
This commit is contained in:
parent
62162fad92
commit
03353ac2c9
@ -12,6 +12,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC rtaudio spdlog mempool Taskflow glfw)
|
||||
|
||||
option(USE_DOUBLE_SAMPLE "Use double sample" OFF)
|
||||
add_definitions(-Dcore_EXPORTS)
|
||||
|
||||
if (MSVC)
|
||||
@ -36,4 +37,10 @@ if (CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILD_DEBUG=1)
|
||||
else()
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC BUILD_DEBUG=0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (USE_DOUBLE_SAMPLE)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC USE_DOUBLE_SAMPLE=1)
|
||||
else()
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC USE_DOUBLE_SAMPLE=0)
|
||||
endif ()
|
@ -17,7 +17,7 @@ int rt_audio_callback(void* output_buffer, void *input_buffer,
|
||||
void* user_data)
|
||||
{
|
||||
auto* API = static_cast<audio_device_manager*>(user_data);
|
||||
return API->stream_callback(static_cast<float*>(output_buffer), static_cast<float*>(input_buffer), frames_nums, stream_time, status);
|
||||
return API->stream_callback(static_cast<sample_t*>(output_buffer), static_cast<sample_t*>(input_buffer), frames_nums, stream_time, status);
|
||||
}
|
||||
|
||||
void audio_device_manager::init(singleton_initliazer& initliazer) {
|
||||
@ -47,7 +47,12 @@ void audio_device_manager::start() {
|
||||
log_current_device_info();
|
||||
|
||||
options_.flags = RTAUDIO_NONINTERLEAVED;
|
||||
auto err = audio_->openStream(&output_params_, input_params, RTAUDIO_FLOAT32, get_sample_rate(), &buffer_size_, &rt_audio_callback, this, &options_);
|
||||
#if USE_DOUBLE_SAMPLE
|
||||
RtAudioFormat format = RTAUDIO_FLOAT64;
|
||||
#else
|
||||
RtAudioFormat format = RTAUDIO_FLOAT32;
|
||||
#endif
|
||||
auto err = audio_->openStream(&output_params_, input_params, format, get_sample_rate(), &buffer_size_, &rt_audio_callback, this, &options_);
|
||||
if (err != RTAUDIO_NO_ERROR) {
|
||||
spdlog::error("failed to open audio stream: {}", audio_->getErrorText());
|
||||
return;
|
||||
@ -86,7 +91,7 @@ uint32_t audio_device_manager::get_output_channel_count() const {
|
||||
return 2; // 现在是固定值, 以后可能会改
|
||||
}
|
||||
|
||||
int audio_device_manager::stream_callback(float* output, float* input, unsigned long frame_count, double stream_time, RtAudioStreamStatus status) {
|
||||
int audio_device_manager::stream_callback(sample_t* output, sample_t* input, unsigned long frame_count, double stream_time, RtAudioStreamStatus status) {
|
||||
if (render_buffers_[0].Num() < frame_count) {
|
||||
// spdlog::warn("render buffer underflow: {}", render_buffers_[0].Num());
|
||||
return 0;
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
[[nodiscard]] CORE_API uint32_t get_input_channel_count() const;
|
||||
[[nodiscard]] CORE_API uint32_t get_output_channel_count() const;
|
||||
|
||||
int stream_callback(float* output, float* input, unsigned long frame_count, double stream_time, RtAudioStreamStatus status);
|
||||
int stream_callback(sample_t* output, sample_t* input, unsigned long frame_count, double stream_time, RtAudioStreamStatus status);
|
||||
void log_all_devices();
|
||||
void log_current_device_info();
|
||||
protected:
|
||||
@ -29,7 +29,7 @@ protected:
|
||||
void stop_render_thread();
|
||||
void render_thread();
|
||||
std::thread render_thread_;
|
||||
std::vector<circular_audio_buffer<float>> render_buffers_;
|
||||
circular_buffer_vector_type render_buffers_;
|
||||
std::atomic_bool render_thread_running_ = false;
|
||||
std::atomic_bool render_thread_should_stop_ = false;
|
||||
#pragma endregion
|
||||
|
@ -15,7 +15,7 @@ void audio_buffer::resize(uint32_t channel_num, uint32_t block_size) {
|
||||
void audio_buffer::clear() {
|
||||
std::scoped_lock lock(lock_);
|
||||
for (auto& channel : buffer_) {
|
||||
std::memset(channel.data(), 0, channel.size() * sizeof(float));
|
||||
std::memset(channel.data(), 0, channel.size() * sizeof(sample_t));
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,9 +41,9 @@ void audio_buffer::multiple(float percent) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float> audio_buffer::get_interleaved_buffer() {
|
||||
std::vector<sample_t> audio_buffer::get_interleaved_buffer() {
|
||||
std::scoped_lock lock(lock_);
|
||||
std::vector<float> result;
|
||||
std::vector<sample_t> result;
|
||||
result.reserve(buffer_[0].size() * buffer_.size());
|
||||
for (uint32_t sample_index = 0; sample_index < buffer_[0].size(); sample_index++) {
|
||||
for (uint32_t channel_index = 0; channel_index < buffer_.size(); channel_index++) {
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
class CORE_API audio_buffer {
|
||||
public:
|
||||
float** get_headers() { return headers_.data(); }
|
||||
const std::vector<float*>& get_headers_vector() { return headers_; }
|
||||
sample_t** get_headers() { return headers_.data(); }
|
||||
const std::vector<sample_t*>& get_headers_vector() { return headers_; }
|
||||
|
||||
[[nodiscard]] uint32_t get_num_channels() const { return buffer_.size(); }
|
||||
[[nodiscard]] uint32_t get_num_samples() const { return buffer_[0].size(); }
|
||||
@ -18,9 +18,9 @@ public:
|
||||
void mix(audio_buffer& in_buffer, float percent = 1.f);
|
||||
void multiple(float percent);
|
||||
|
||||
[[nodiscard]] std::vector<float> get_interleaved_buffer();
|
||||
[[nodiscard]] std::vector<sample_t> get_interleaved_buffer();
|
||||
private:
|
||||
std::vector<std::vector<float>> buffer_;
|
||||
std::vector<float*> headers_{};
|
||||
std::vector<std::vector<sample_t>> buffer_;
|
||||
std::vector<sample_t*> headers_{};
|
||||
std::mutex lock_{};
|
||||
};
|
||||
|
@ -288,8 +288,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
using ui_buffer_type = circular_audio_buffer<float>;
|
||||
using ui_buffer_vector_type = std::vector<ui_buffer_type>;
|
||||
using circular_buffer_type = circular_audio_buffer<sample_t>;
|
||||
using circular_buffer_vector_type = std::vector<circular_buffer_type>;
|
||||
|
||||
#undef checkf
|
||||
#undef check
|
@ -4,6 +4,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
class mixer_track;
|
||||
class channel_node;
|
||||
|
||||
@ -20,8 +22,8 @@ public:
|
||||
uint32_t get_input_node_index(channel_node* node);
|
||||
uint32_t get_output_node_index(channel_node* node);
|
||||
|
||||
float** get_input_headers() { return input_headers_.data(); }
|
||||
float** get_output_headers() { return output_headers_.data(); }
|
||||
sample_t** get_input_headers() { return input_headers_.data(); }
|
||||
sample_t** get_output_headers() { return output_headers_.data(); }
|
||||
|
||||
void set_input_channel_node_name(uint32_t node_index, uint32_t channel_index, const std::string& name);
|
||||
void set_output_channel_node_name(uint32_t node_index, uint32_t channel_index, const std::string& name);
|
||||
@ -37,8 +39,8 @@ public:
|
||||
private:
|
||||
std::map<uint32_t, std::map<uint32_t, std::string>> input_channel_names_;
|
||||
std::map<uint32_t, std::map<uint32_t, std::string>> output_channel_names_;
|
||||
std::vector<float*> input_headers_;
|
||||
std::vector<float*> output_headers_;
|
||||
std::vector<sample_t*> input_headers_;
|
||||
std::vector<sample_t*> output_headers_;
|
||||
};
|
||||
|
||||
class mixer_channel_interface : public channel_interface {
|
||||
|
@ -13,6 +13,6 @@ mixer_channel_node::mixer_channel_node(channel_interface* in_owner, mixer_track*
|
||||
channel_headers_.push_back(headers[in_node_index * 2 + 1]);
|
||||
}
|
||||
|
||||
const std::vector<float*>& null_channel_node::get_channel_headers() {
|
||||
const std::vector<sample_t*>& null_channel_node::get_channel_headers() {
|
||||
return g_mixer.zero_track->buffer.get_headers_vector();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "extern.h"
|
||||
|
||||
class mixer_track;
|
||||
class channel_interface;
|
||||
@ -18,7 +19,7 @@ public:
|
||||
|
||||
channel_node(channel_interface* in_owner, channel_node_type in_type) : owner(in_owner), type(in_type) {}
|
||||
|
||||
virtual const std::vector<float*>& get_channel_headers() = 0;
|
||||
virtual const std::vector<sample_t*>& get_channel_headers() = 0;
|
||||
virtual std::string get_name() = 0;
|
||||
|
||||
channel_interface* owner;
|
||||
@ -29,13 +30,13 @@ class mixer_channel_node : public channel_node {
|
||||
public:
|
||||
mixer_channel_node(channel_interface* in_owner, mixer_track* in_track, uint32_t in_node_index);
|
||||
|
||||
const std::vector<float*>& get_channel_headers() override { return channel_headers_; }
|
||||
const std::vector<sample_t*>& get_channel_headers() override { return channel_headers_; }
|
||||
std::string get_name() override { return "MixerChannelNode"; }
|
||||
|
||||
[[nodiscard]] mixer_track* get_track() const { return track_; }
|
||||
private:
|
||||
mixer_track* track_;
|
||||
std::vector<float*> channel_headers_;
|
||||
std::vector<sample_t*> channel_headers_;
|
||||
uint32_t node_index_;
|
||||
};
|
||||
|
||||
@ -48,5 +49,5 @@ public:
|
||||
static null_channel_node* get() { return instance; }
|
||||
std::string get_name() override { return "NullChannelNode"; }
|
||||
|
||||
const std::vector<float*>& get_channel_headers() override;
|
||||
const std::vector<sample_t*>& get_channel_headers() override;
|
||||
};
|
||||
|
@ -57,7 +57,7 @@ void mixer_track::process(uint32_t in_frames) {
|
||||
void mixer_track::post_process(uint32_t in_frames) {
|
||||
buffer.multiple(get_volume());
|
||||
for (int i = 0; i < buffer.get_num_channels(); ++i) {
|
||||
ui_buffer_type& ui_buffer = (*ui_buffers)[i];
|
||||
auto& ui_buffer = (*ui_buffers)[i];
|
||||
ui_buffer.Push(buffer.get_headers()[i], in_frames);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ struct mixer_track_link {
|
||||
class mixer_track {
|
||||
public:
|
||||
explicit mixer_track(mixer_track_type in_type) : type_(in_type) {
|
||||
ui_buffers = std::make_shared<ui_buffer_vector_type>();
|
||||
ui_buffers = std::make_shared<circular_buffer_vector_type>();
|
||||
}
|
||||
virtual ~mixer_track();
|
||||
|
||||
@ -37,7 +37,7 @@ public:
|
||||
virtual void rename(const std::string& in_name) = 0;
|
||||
[[nodiscard]] virtual std::string get_name() const = 0;
|
||||
|
||||
[[nodiscard]] float** get_headers() { return buffer.get_headers(); }
|
||||
[[nodiscard]] sample_t** get_headers() { return buffer.get_headers(); }
|
||||
|
||||
[[nodiscard]] mixer_track_type get_type() const { return type_; }
|
||||
|
||||
@ -47,7 +47,7 @@ public:
|
||||
[[nodiscard]] float get_volume() const { return volume; }
|
||||
|
||||
audio_buffer buffer;
|
||||
std::shared_ptr<ui_buffer_vector_type> ui_buffers;
|
||||
std::shared_ptr<circular_buffer_vector_type> ui_buffers;
|
||||
std::vector<plugin_host*> effects{};
|
||||
std::vector<mixer_track_link> children{};
|
||||
multicast_delegate<mixer_track*> on_processed;
|
||||
|
@ -9,10 +9,10 @@ plugin_host::~plugin_host() {
|
||||
|
||||
void plugin_host::on_update_buffer_size(int buffer_size)
|
||||
{
|
||||
ui_buffers = std::make_shared<ui_buffer_vector_type>();
|
||||
ui_buffers = std::make_shared<circular_buffer_vector_type>();
|
||||
for (uint32_t i = 0; i < get_output_channels(); i++)
|
||||
{
|
||||
ui_buffer_type buffer(buffer_size * 3);
|
||||
circular_buffer_type buffer(buffer_size * 3);
|
||||
ui_buffers->emplace_back(std::move(buffer));
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
channel_interface* channel = nullptr;
|
||||
std::vector<mixer_track*> owner_tracks;
|
||||
bool editor_opened = false;
|
||||
std::shared_ptr<ui_buffer_vector_type> ui_buffers;
|
||||
std::shared_ptr<circular_buffer_vector_type> ui_buffers;
|
||||
protected:
|
||||
void create_and_open_editor();
|
||||
void destroy_editor();
|
||||
|
@ -217,7 +217,12 @@ void vst2_plugin_host::update_channel_node_name() {
|
||||
|
||||
void vst2_plugin_host::process(uint32_t frame_num) {
|
||||
// TODO send midi
|
||||
#if USE_DOUBLE_SAMPLE
|
||||
effect_->processDoubleReplacing(effect_, channel->get_input_headers(), channel->get_output_headers(), frame_num);
|
||||
#else
|
||||
effect_->processReplacing(effect_, channel->get_input_headers(), channel->get_output_headers(), frame_num);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < ui_buffers->size(); ++i)
|
||||
{
|
||||
ui_buffers->at(i).Push(channel->get_output_headers()[i], frame_num);
|
||||
|
@ -15,3 +15,9 @@
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
|
||||
#if USE_DOUBLE_SAMPLE
|
||||
typedef double sample_t;
|
||||
#else
|
||||
typedef float sample_t;
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user