- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试将 opus 集成到我的应用程序中,编码和解码函数返回正值,这意味着成功,但输出音频无法播放。原始音频数据也可以播放。这是我对数据进行编码的方式。我使用 4 字节前缀来分隔每个数据包。
self.encoder = opus_encoder_create(24000, 1, OPUS_APPLICATION_VOIP, &opusError);
opus_encoder_ctl(self.encoder, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
- (void) encodeBufferList:(AudioBufferList *)bufferList {
BOOL success = TPCircularBufferProduceBytes(_circularBuffer, bufferList->mBuffers[0].mData, bufferList->mBuffers[0].mDataByteSize);
if (!success) {
NSLog(@"insufficient space in circular buffer!");
}
if (!_encoding) {
_encoding = YES;
dispatch_async(self.processingQueue, ^{
[self startEncodingLoop];
});
}
}
-(void)startEncodingLoop
{
int32_t availableBytes = 0;
opus_int16 *data = (opus_int16*)TPCircularBufferTail(_circularBuffer, &availableBytes);
int availableSamples = availableBytes / _inputASBD.mBytesPerFrame;
/*!
* Use dynamic duration
*/
// int validSamples[6] = {2.5, 5, 10, 20, 40, 60}; // in milisecond
// int esample = validSamples[0] * self.sampleRate / 1000;
// for (int i = 0; i < 6; i++) {
// int32_t samp = validSamples[i] * self.sampleRate / 1000;
// if (availableSamples < samp) {
// break;
// }
// esample = samp;
// }
/*!
* Use 20ms
*/
int esample = 20 * self.sampleRate / 1000;
if (availableSamples < esample) {
/*!
* Out of data. Finish encoding
*/
self.encoding = NO;
[self.eDelegate didFinishEncode];
return;
}
// printf("raw input value for packet \n");
// for (int i = 0; i < esample * self.numberOfChannels; i++) {
// printf("%d :", data[i]);
// }
int returnValue = opus_encode(_encoder, data, esample, _encoderOutputBuffer, 1000);
TPCircularBufferConsume(_circularBuffer, esample * sizeof(opus_int16) * self.numberOfChannels);
// printf("output encode \n");
// for (int i = 0; i < returnValue; i++) {
// printf("%d :", _encoderOutputBuffer[i]);
// }
NSMutableData *outputData = [NSMutableData new];
NSError *error = nil;
if (returnValue <= 0) {
error = [OKUtilities errorForOpusErrorCode:returnValue];
}else {
[outputData appendBytes:_encoderOutputBuffer length:returnValue * sizeof(unsigned char)];
unsigned char int_field[4];
int_to_char(returnValue , int_field);
NSData *header = [NSData dataWithBytes:&int_field[0] length:4 * sizeof(unsigned char)];
if (self.eDelegate) {
[self.eDelegate didEncodeWithData:header];
}
}
if (self.eDelegate) {
[self.eDelegate didEncodeWithData:outputData];
}
[self startEncodingLoop];
}
这里是解码函数:
self.decoder = opus_decoder_create(24000, 1, &opusError);
opus_decoder_ctl(self.decoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
opus_decoder_ctl(self.decoder, OPUS_SET_GAIN(10));
-(void)startParseData:(unsigned char*)data remainingLen:(int)len
{
if (len <= 0) {
[self.dDelegate didFinishDecode];
return;
}
int headLen = sizeof(unsigned char) * 4;
unsigned char h[4];
h[0] = data[0];
h[1] = data[1];
h[2] = data[2];
h[3] = data[3];
int packetLen = char_to_int(h);
data += headLen;
packetLen = packetLen * sizeof(unsigned char) * self.numberOfChannels;
[self decodePacket:data length:packetLen remainingLen:len - headLen];
}
-(void)decodePacket:(unsigned char*)inputData length:(int)len remainingLen:(int)rl
{
int bw = opus_packet_get_bandwidth(inputData); //TEST: return OPUS_BANDWIDTH_SUPERWIDEBAND here
int32_t decodedSamples = 0;
// int validSamples[6] = {2.5, 5, 10, 20, 40, 60}; // in milisecond
/*!
* Use 60ms
*/
int esample = 60 * self.sampleRate / 1000;
// printf("input decode \n");
// for (int i = 0; i < len; i++) {
// printf("%d :", inputData[i]);
// }
_decoderBufferLength = esample * self.numberOfChannels * sizeof(opus_int16);
int returnValue = opus_decode(_decoder, inputData, len, _outputBuffer, esample, 1);
if (returnValue < 0) {
NSError *error = [OKUtilities errorForOpusErrorCode:returnValue];
NSLog(@"decode error %@", error);
inputData += len;
[self startParseData:inputData remainingLen:rl - len];
return;
}
decodedSamples = returnValue;
NSUInteger length = decodedSamples * self.numberOfChannels;
// printf("raw decoded data \n");
// for (int i = 0; i < length; i++) {
// printf("%d :", _outputBuffer[i]);
// }
NSData *audioData = [NSData dataWithBytes:_outputBuffer length:length * sizeof(opus_int16)];
if (self.dDelegate) {
[self.dDelegate didDecodeData:audioData];
}
inputData += len;
[self startParseData:inputData remainingLen:rl - len];
}
请帮我指出我遗漏了什么。一个例子会很棒。
最佳答案
我认为问题出在解码端:
您将 1
作为 fec
参数传递给 opus_decode()
.这要求解码器根据当前数据包中的纠错数据生成完整数据包持续时间的数据。我在您的代码中没有看到任何丢失的数据包跟踪,因此应该传递 0
。通过该更改,您的输入和输出持续时间应该匹配。
您将解码器配置为单声道输出,但稍后在长度计算中使用 self.numberOfChannels
。这些应该匹配,否则您可能会遇到意外行为。
OPUS_SET_SIGNAL
不会在 opus_decoder_ctl() 中执行任何操作,但它只会返回 OPUS_UNIMPLEMENTED 而不会影响行为。
Opus 数据包的持续时间最长可达 120 毫秒,因此 60 毫秒的限制可能无法解码某些流。如果您只与自己的应用对话,那么您的配置不会导致问题,因为 libopus 默认为 20 毫秒帧。
关于ios - 如何使用 opus 编码和解码音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30448006/
我正在导入 Telegram android应用进入android studio。 这个项目包含很多.C文件,所以我不得不用Android NDK转换这个C文件来生成lib文件夹,最后结束导入过程!
我正在开发使用 libavcodec 库的库。 我尝试使用 opus 编解码器对音频帧进行编码,但是在 avcodec_open2(...) 之后我得到了这个日志 [opus @ 0x2335f30]
在javascript网页上,我使用HTML5 Media API生成了一条音频消息,然后通过socketio将其发送到将文件保存在磁盘上的nodejs服务器。一切正常。 Javascript块,客户
我正在使用这些代码行。 val uri = getUriForFile(this, BuildConfig.APPLICATION_ID+ ".provider" , file!!)
在仍在学习 Go 的过程中,我正在尝试正确读取 Opus 文件并将其发送到 Discord 的语音 channel 。 (仅支持 Opus 编解码器)。最初使用 this我能够传递一个 WAV,该脚本
函数 opus_encode 需要帧大小作为参数。在 api 文档中,它说缓冲区大小是每个 channel 的样本数。但是如何确定我应该使用哪种尺寸呢? 我在 android 中使用 opus。采样率
我已经在 gitbash 中使用 pip 安装了适用于 python 3.4 的最新版本的 opus $ pip install --upgrade opuslib Requirement alrea
我正在寻找一种将 opus-codec(解码器部分)与我的 Android 应用程序集成的方法。 你知道有任何实现这样做吗?我们目前正在使用 ogg-vorbis 进行语音提示,考虑使用 speex(
我对为 .opus 文件编写元数据很感兴趣,但到目前为止我看到的所有帖子都是针对更主流的格式,例如 .ogg 或 .mp3。我不确定 ID3 标签是否适用于 .opus 文件,而且我找不到任何资源说明
我正在尝试将 opus 集成到我的应用程序中,编码和解码函数返回正值,这意味着成功,但输出音频无法播放。原始音频数据也可以播放。这是我对数据进行编码的方式。我使用 4 字节前缀来分隔每个数据包。 se
我正在捕获一个语音聊天程序的音频流(它是专有的、闭源的,我无法控制它),它是用 OPUS Codec 编码的,我想将其解码为原始 PCM 音频 ( Opus Decoder doc )。 我正在做的是
我目前正在编写一个小脚本,可以将 MP4 动态转换为 Opus 音频并将其发送到 Discord在戈朗。最初我的脚本会在通过 stdin 下载到 ffmpeg 时传递 MP4,然后将 stdout 传
我正在尝试将 Opus 文件解码回原始 48 kHz。但是我找不到任何示例代码来做到这一点。 我当前的代码是这样的: void COpusCodec::Decode(unsigned char* en
就像我想添加/更改元数据到 ogg(opus) 的标题一个文件夹中的文件(一张专辑/一位艺术家)。当我从 wav/flac 编码时至opus我通常用 for f in *.*; do ffmpeg -
我正在尝试将 OGG_OPUS 编码流发送到谷歌的语音到文本流服务。 由于 Google 对其流请求施加了时间限制,因此我必须以固定的时间间隔将音频流路由到另一个 Google Speech To T
我已经用谷歌搜索过这个问题,但没有得到明确的答案。 据我了解,FLV 容器格式目前支持以下音频格式 MP3、ADPCM、线性 PCM、Nellymoser、Speex、AAC、G.711(保留供内部使
我正在使用 WebRTC 从网页录制输入麦克风并通过 SoX 进行处理。 问题是,Firefox 录音采用 Opus Audio 格式(根据 VLC 媒体信息),位于 Ogg 容器中,而 SoX 不喜
我正在开发一个 webRTC Web 应用程序,到目前为止效果非常好。例如,我还没有弄清楚如何告诉 Opus 编解码器(强制)使用“全频段”。 将编解码器设置为 510 kHz 比特率很简单: des
我正在使用C语言在Linux环境下开发一个webrtc模拟器。在这里,我需要将媒体从一个 webrtc 模拟器发送到另一个 webrtc 模拟器。我需要使用 VP8 和 Opus 编解码器。现在我开始
是否可以配置 PJSIP (PJSUA2)使用OPUS编解码器? 最佳答案 我终于找到了一个方法(ubuntu 14.04,要求 PJSIP >= 2.5): 使用以下命令从源代码安装 opus@1.
我是一名优秀的程序员,十分优秀!