8
8
9
9
#include " roc_audio/vorbis_encoder.h"
10
10
#include " roc_core/panic.h"
11
+ #include < iostream>
11
12
12
13
namespace roc {
13
14
namespace audio {
@@ -18,9 +19,9 @@ VorbisEncoder::VorbisEncoder(const SampleSpec& sample_spec)
18
19
, frame_size_(0 ) {
19
20
vorbis_info_init (&vorbis_info_);
20
21
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 );
24
25
if (ret != 0 ) {
25
26
roc_panic (" vorbis encoder: failed to initialize vorbis encoder" );
26
27
}
@@ -56,22 +57,16 @@ status::StatusCode VorbisEncoder::init_status() const {
56
57
57
58
size_t VorbisEncoder::encoded_byte_count (size_t num_samples) const {
58
59
if (!initialized_) {
60
+ roc_panic (" vorbis encoder: encoder not initialized" );
59
61
return 0 ;
60
62
}
61
63
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);
71
67
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;
75
70
}
76
71
77
72
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) {
84
79
}
85
80
86
81
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;
89
100
}
90
101
91
102
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);
93
171
}
94
172
95
173
} // namespace audio
0 commit comments