Skip to content

Commit 4488193

Browse files
committed
write_samples WIP
1 parent 551e31c commit 4488193

File tree

2 files changed

+104
-19
lines changed

2 files changed

+104
-19
lines changed

src/internal_modules/roc_audio/target_libvorbis/roc_audio/vorbis_encoder.cpp

+96-18
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "roc_audio/vorbis_encoder.h"
1010
#include "roc_core/panic.h"
11+
#include <iostream>
1112

1213
namespace roc {
1314
namespace audio {
@@ -18,9 +19,9 @@ VorbisEncoder::VorbisEncoder(const SampleSpec& sample_spec)
1819
, frame_size_(0) {
1920
vorbis_info_init(&vorbis_info_);
2021

21-
const int num_channels = static_cast<int>(sample_spec.num_channels());
22-
const int sample_rate = static_cast<int>(sample_spec.sample_rate());
23-
int ret = vorbis_encode_init_vbr(&vorbis_info_, num_channels, sample_rate, 0.0f);
22+
const long num_channels = static_cast<long>(sample_spec.num_channels());
23+
const long sample_rate = static_cast<long>(sample_spec.sample_rate());
24+
int ret = vorbis_encode_init_vbr(&vorbis_info_, num_channels, sample_rate, 0.5f);
2425
if (ret != 0) {
2526
roc_panic("vorbis encoder: failed to initialize vorbis encoder");
2627
}
@@ -56,22 +57,16 @@ status::StatusCode VorbisEncoder::init_status() const {
5657

5758
size_t VorbisEncoder::encoded_byte_count(size_t num_samples) const {
5859
if (!initialized_) {
60+
roc_panic("vorbis encoder: encoder not initialized");
5961
return 0;
6062
}
6163

62-
if (vorbis_info_.rate <= 0 || vorbis_info_.channels <= 0
63-
|| vorbis_info_.bitrate_nominal <= 0) {
64-
roc_panic("vorbis encoder: vorbis_info structure has invalid values");
65-
return 0;
66-
}
67-
68-
// Average number of bits used per sample, per channel.
69-
const size_t bit_width = static_cast<size_t>(
70-
(vorbis_info_.bitrate_nominal / vorbis_info_.rate) / vorbis_info_.channels);
64+
const size_t channels = static_cast<size_t>(vorbis_info_.channels);
65+
// const size_t sample_rate = static_cast<size_t>(vorbis_info_.rate);
66+
// const size_t bitrate_nominal = static_cast<size_t>(vorbis_info_.bitrate_nominal);
7167

72-
const size_t encoded_bytes = (num_samples * bit_width + 7) / 8;
73-
74-
return encoded_bytes;
68+
size_t estimated_bytes = (32 * num_samples * channels) / (8);
69+
return estimated_bytes;
7570
}
7671

7772
void VorbisEncoder::begin_frame(void* frame_data, size_t frame_size) {
@@ -84,12 +79,95 @@ void VorbisEncoder::begin_frame(void* frame_data, size_t frame_size) {
8479
}
8580

8681
size_t VorbisEncoder::write_samples(const sample_t* samples, size_t n_samples) {
87-
roc_panic("TODO");
88-
return 0;
82+
if (!initialized_) {
83+
roc_panic("vorbis encoder: encoder not initialized");
84+
return 0;
85+
}
86+
87+
if (!samples || n_samples == 0) {
88+
return 0;
89+
}
90+
91+
buffer_samples_(samples, n_samples);
92+
93+
size_t total_bytes_written = process_analysis_and_encoding_();
94+
95+
vorbis_analysis_wrote(&vorbis_dsp_, 0);
96+
97+
total_bytes_written += process_analysis_and_encoding_();
98+
99+
return total_bytes_written;
89100
}
90101

91102
void VorbisEncoder::end_frame() {
92-
roc_panic("TODO");
103+
frame_data_ = NULL;
104+
frame_size_ = 0;
105+
}
106+
107+
void VorbisEncoder::buffer_samples_(const sample_t* samples, size_t n_samples) {
108+
const int int_n_samples = static_cast<int>(n_samples);
109+
110+
float** buffer = vorbis_analysis_buffer(&vorbis_dsp_, int_n_samples);
111+
112+
for (int i = 0; i < int_n_samples; ++i) {
113+
for (int ch = 0; ch < vorbis_info_.channels; ++ch) {
114+
buffer[ch][i] = samples[i * vorbis_info_.channels + ch];
115+
}
116+
}
117+
118+
vorbis_analysis_wrote(&vorbis_dsp_, int_n_samples);
119+
}
120+
121+
size_t VorbisEncoder::process_analysis_and_encoding_() {
122+
size_t total_bytes_written = 0;
123+
124+
while (vorbis_analysis_blockout(&vorbis_dsp_, &vorbis_block_) == 1) {
125+
vorbis_analysis(&vorbis_block_, NULL);
126+
127+
vorbis_bitrate_addblock(&vorbis_block_);
128+
129+
total_bytes_written += extract_and_write_packets_();
130+
}
131+
132+
return total_bytes_written;
133+
}
134+
135+
size_t VorbisEncoder::extract_and_write_packets_() {
136+
size_t bytes_written = 0;
137+
138+
ogg_packet packet;
139+
while (vorbis_bitrate_flushpacket(&vorbis_dsp_, &packet)) {
140+
ogg_stream_packetin(&ogg_stream_, &packet);
141+
142+
bytes_written += write_ogg_pages_();
143+
}
144+
145+
return bytes_written;
146+
}
147+
148+
size_t VorbisEncoder::write_ogg_pages_() {
149+
long bytes_written = 0;
150+
151+
ogg_page page;
152+
while (ogg_stream_pageout(&ogg_stream_, &page)) {
153+
if (bytes_written + page.header_len + page.body_len
154+
> static_cast<long>(frame_size_)) {
155+
roc_panic("vorbis encoder: frame buffer overflow");
156+
}
157+
158+
write_to_frame_(page.header, page.header_len, bytes_written);
159+
bytes_written += page.header_len;
160+
161+
write_to_frame_(page.body, page.body_len, bytes_written);
162+
bytes_written += page.body_len;
163+
}
164+
165+
return static_cast<size_t>(bytes_written);
166+
}
167+
168+
void VorbisEncoder::write_to_frame_(const void* data, long size, long offset) {
169+
const size_t casted_size = static_cast<size_t>(size);
170+
memcpy(static_cast<uint8_t*>(frame_data_) + offset, data, casted_size);
93171
}
94172

95173
} // namespace audio

src/internal_modules/roc_audio/target_libvorbis/roc_audio/vorbis_encoder.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
*/
88

99
//! @file roc_audio/target_libvorbis/roc_audio/vorbis_encoder.h
10-
//! @brief Vorbis audio decoder.
10+
//! @brief Vorbis audio encoder.
1111

1212
#ifndef ROC_AUDIO_VORBIS_ENCODER_H_
1313
#define ROC_AUDIO_VORBIS_ENCODER_H_
1414

1515
#include "roc_audio/iframe_encoder.h"
1616
#include "roc_audio/sample_spec.h"
17+
#include <vorbis/codec.h>
1718
#include <vorbis/vorbisenc.h>
1819

1920
namespace roc {
@@ -44,6 +45,12 @@ class VorbisEncoder : public IFrameEncoder {
4445
virtual void end_frame();
4546

4647
private:
48+
void buffer_samples_(const sample_t* samples, size_t n_samples);
49+
size_t process_analysis_and_encoding_();
50+
size_t extract_and_write_packets_();
51+
size_t write_ogg_pages_();
52+
void write_to_frame_(const void* data, long size, long offset);
53+
4754
bool initialized_;
4855
void* frame_data_;
4956
size_t frame_size_;

0 commit comments

Comments
 (0)