Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opus_encode returns OPUS_BAD_ARG with srate=48kHz and frame size = 320 #228

Closed
Hirrolot opened this issue Jun 19, 2021 · 2 comments
Closed

Comments

@Hirrolot
Copy link

I've set up my hardware to generate 48kHz PCM stream, within only 1 channel. Therefore, it generates 48000 / 320 = 150 frames per second. The problem is that I get OPUS_BAD_ARG from opus_encode caused by this piece of code:

if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs &&

libopus thinks that 150 frames per second is invalid. Is it possible to solve the problem?

How to reproduce

#include <opus/opus.h>

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

#define FILE_SIZE (320 * 1000)
#define FRAMES_COUNT 500
#define FRAME_SIZE 320

int main(void) {
	int error;
	OpusEncoder *enc;
	enc = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &error);
	assert(error == OPUS_OK);

	FILE *fp = fopen("audio.pcm", "rb");
	assert(fp);

	char *data = malloc(FILE_SIZE);
	assert(data);
	fread(data, 1, FILE_SIZE, fp);

	char *out = malloc(4000);
	assert(out);

	for (size_t i = 0; i < FRAMES_COUNT; i++) {
		int bytes_written = opus_encode(enc, data + (i * FRAME_SIZE), FRAME_SIZE, out, 4000);
		if (bytes_written < 0) {
			if (bytes_written == OPUS_BAD_ARG) {
				abort(); // Fails
			}
		}
	}
}

The stream itself: audio.pcm.tar.gz.

Compiling:

$ gcc test_opus.c -lopus
@Hirrolot Hirrolot changed the title OPUS_BAD_ARG with srate=48kHz and frame size = 320 opus_encode returns OPUS_BAD_ARG with srate=48kHz and frame size = 320 Jun 19, 2021
@rillian
Copy link
Contributor

rillian commented Jun 19, 2021

No, it's not possible to run the encoder at 150 frames a second. You must use a supported frame size. If your hardware isn't capable of using one of the possible frame sizes, you can insert a small ringbuffer to compensate.

We recommend 960 sample frames (20 ms at 48 kHz, or 50 frames per second) for most applications. Frames shorter than 10 ms reduce quality with little improvement to delay unless you're doing live audio.

int bytes_written = opus_encode(enc, data + (i * FRAME_SIZE), FRAME_SIZE, out, 4000);

Another issue is that the third argument to opus_encode is the number of samples, not the number of bytes. If you're reading 16-bit mono audio into a char * you need to divide by two when you pass the in input frame size.

@Hirrolot
Copy link
Author

Thanks, with frame size = 960 it worked.

Another issue is that the third argument to opus_encode is the number of samples, not the number of bytes. If you're reading 16-bit mono audio into a char * you need to divide by two when you pass the in input frame size.

In fact, FRAME_SIZE here is the number of samples, but I provide data + (i * FRAME_SIZE) as the second argument to opus_encode, which is wrong; data + (i * FRAME_SIZE * 2) would be correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants