xiph / libopusenc Goto Github PK
View Code? Open in Web Editor NEWLibrary for encoding .opus audio files and live streams.
License: BSD 3-Clause "New" or "Revised" License
Library for encoding .opus audio files and live streams.
License: BSD 3-Clause "New" or "Revised" License
Hello,
I'm using libopusenc with an ARM cortex-m4 device and there are some feature that could be useful:
Avoid resampling with rates supported by opus (8000, 12000, 16000, 24000, and 48000). Resampling in a powerfull CPU isn't a problem, but in a small MCU is a heavy proces.
Support use 16 and 32 integers as input and don't use float API all the time.
I tried to do this changes in the libopusenc by myself, but granule position is a mess. Finally I have created a version of opusenc.c (from opus-tools) to test my system, but I think it would be fantastic if libopusenc could be used for small systems.
br.
Not very often, but maybe 1 in 50 times, I get a crash with the above-mentioned log.
assert(enc->buffer_end <= BUFFER_SAMPLES);
encode_buffer(enc);
if (enc->unrecoverable) return enc->unrecoverable;
/* Draining should have called all the streams to complete. */
assert(enc->streams == NULL); /* <-- the line where the crash happens */
return OPE_OK;
}
Of course I'd much rather have this NOT crashing. What can I do in order to prevent this from happening? Can there be a "bad moment" to call the drain() such as immediately after starting to encode (which is how I was able to reproduce the bug if it wasn't a coincidence). Should I check for anything else before draining so I don't run into the assert?
Sorry for the dumb question but is C thread safe in this regard or could calling drain() and a simultaneous ope_encoder_write[/_float] cause this?
Seeing this error
make: *** No rule to make target '/Users/monashreer/opus/android-opus-codec/app/src/main/jni/libopusenc/..//Users/monashreer/opus/android-opus-codec/app/src/main/jni/libopusenc/src/opusenc.c', needed by '/Users/monashreer/opus/android-opus-codec/app/src/main/obj/local/armeabi-v7a/objs/opusenc/__//Users/monashreer/opus/android-opus-codec/app/src/main/jni/libopusenc/src/opusenc.o'.
Android.mk file
#Build libopusenc
include $(CLEAR_VARS)
LOCAL_PATH := $(ROOT)/libopusenc
LOCAL_MODULE := opusenc
LOCAL_SRC_FILES := \
$(addprefix ../, $(shell cd $(LOCAL_PATH)/../; \
find $(LOCAL_PATH)/src -type f -name '*.c'))
# LOCAL_LDLIBS += -llog -lOpenSLES -logg -lopus -L$(LOCAL_PATH)/lib
LOCAL_C_INCLUDES := \
$(ROOT)/include \
$(LOCAL_PATH)/include
LOCAL_CFLAGS := -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT=1 -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errno
LOCAL_CFLAGS += -DNDEBUG
LOCAL_CFLAGS += -O3
LOCAL_CFLAGS += -DPACKAGE_NAME='"CHANGE THE PACKAGE NAME"'
LOCAL_CFLAGS += -DPACKAGE_VERSION='"1.0.0"'
LOCAL_CFLAGS += -DEXPORT=
LOCAL_CPPFLAGS := -DBSD=1
LOCAL_CPPFLAGS += -ffast-math -O3 -funroll-loops
LOCAL_STATIC_LIBRARIES := opus
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)
Currently, the speex resampler is always build with -DFLOATING_POINT
.
Would be great to allow building with fixed point support.
I have to make this library for four different architectures. I was able to make that library for my computer's architecture by installing opus with brew. However, I now need to do the configure routine in a way that it checks for opus in my generated libopus.a
file (that's built by me for these 4 libraries). Wherever I put the libopus.a
and whatever options I try to add to the call it always tells me
checking pkg-config is at least version 0.9.0... yes
checking for DEPS... no
configure: error: Package requirements (opus >= 1.1) were not met:
No package 'opus' found
on my ./configure
I did export DEPS_LIBS=$HOME/Downloads/libopusenc-iOS/libopus.a
and now the whole process gets much further but it stops at
------------------------------------------------------------------------
libopusenc 0.2.1: Automatic configuration OK.
Hidden visibility ............ yes
API code examples ............ yes
API documentation ............ no
------------------------------------------------------------------------
/Applications/Xcode.app/Contents/Developer/usr/bin/make all-am
CCLD libopusenc.la
*** Warning: Linking the shared library libopusenc.la against the
*** static library /Users/T/Downloads/libopusenc-iOS/libopus.a is not portable!
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: archive member: .libs/libopusenc.a(libopus.a) fat file for cputype (7) cpusubtype (3) is not an object file (bad magic number)
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar: internal ranlib command failed
make[1]: *** [libopusenc.la] Error 1
make: *** [all] Error 2
Where am I taking the wrong step to receive this error? I'm just encoding a simple audio (recorded in 8kHz with 20ms frames and 8 kbps) not sure what went wrong but this seems to be a very random error, sometimes it happens, sometimes it doesn't.
https://github.com/xiph/libopusenc/blob/master/src/ogg_packer.c#L273
In libopusenc's opusenc.c line 194, calling ambisonics is guarded by OPUS_HAVE_OPUS_PROJECTION_H, while in opus, they're guarded by ENABLE_EXPERIMENTAL_AMBISONICS. I have opus_projection.h, since I have the most recent commits, but I've intentionally not defined ENABLE_EXPERIMENTAL_AMBISONICS, so I get link errors. Easy enough to work around, but an error nonetheless.
CC src/resample.lo
src/resample.c: In function ‘resampler_basic_zero’:
src/resample.c:567:106: warning: unused parameter ‘in’ [-Wunused-parameter]
static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
~~~~~~~~~~~~~~~~~~~~^~
src/resample.c: In function ‘libopusenc_resampler_init_frac’:
src/resample.c:803:17: warning: unused variable ‘i’ [-Wunused-variable]
spx_uint32_t i;
^
I integrated opus enc library(version 0.2.1) to Android platform. but I collected some crash when opus encode destory. error backstrace as following:
1 #00 pc 0006828e /system/lib/libc.so (je_huge_salloc+133) [armeabi-v7a]
2 #01 pc 0006d303 /system/lib/libc.so (ifree+274) [armeabi-v7a]
3 #02 pc 0006d65d /system/lib/libc.so (je_free+72) [armeabi-v7a]
4 #03 pc 000025ef libopusenc.so ope_encoder_destroy [armeabi-v7a]
or
1 #00 pc 0006d22c /system/lib/libc.so (ifree+59) [armeabi-v7a]
2 #01 pc 0006d65d /system/lib/libc.so (je_free+72) [armeabi-v7a]
3 #02 pc 00002621 libopusenc.so ope_encoder_destroy [armeabi-v7a]
so, how can I resolved this crash? Is it possible to catch this crash or could you provide some information to help me to debug? Thanks. (sorry for my poor english.)
opusenc
documentation includes this at NOTES
While it is possible to use opusenc for low latency streaming (e.g. with --max-delay 0 and netcat instead of Icecast) it's not really designed for this, and the Ogg container and TCP transport aren't the best tools for that application. Shell pipelines themselves will often have high buffering. The ability to set framesizes as low as 2.5 ms in opusenc mostly exists to try out the quality of the format with low latency settings, but not really for actual low latency usage. Interactive usage should use UDP/RTP directly.
For the use case of a user-defined infinite stream, that is, using the output of opusenc
as the source of a Web radio station, are there any technical limitations for the configuration of using a dedicated Linux machine to run opusenc
indefinitely, commenced from a shell script e.g.,
<?php
if (isset($_GET["start"])) {
header("Access-Control-Allow-Origin: *");
header("Content-Type: audio/x-opus+ogg");
echo passthru("parec -v --record --rate=48000 --device=alsa_output.pci-0000_00_N.analog-stereo.monitor | opusenc --expect-loss=25 --max-delay=0 --framesize=2.5 --bitrate=256 --raw - -");
exit();
}
document.querySelector('audio').src = 'index.php?start=true';
Why it is not possible to explicitly set frame duration to default (OPUS_FRAMESIZE_ARG)
ope_encoder_ctl(encoder_.get(), OPUS_SET_EXPERT_FRAME_DURATION(static_cast<opus_int32>(frameSize)));
Probably method ope_encoder_ctl() has an inconsistant check:
case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
int max_supported = OPUS_FRAMESIZE_60_MS;
#ifdef OPUS_FRAMESIZE_120_MS
max_supported = OPUS_FRAMESIZE_120_MS;
#endif
if (value < OPUS_FRAMESIZE_2_5_MS || value > max_supported) {
ret = OPUS_UNIMPLEMENTED;
break;
}
ret = opeint_encoder_ctl(&enc->st, OPUS_SET_EXPERT_FRAME_DURATION(value));
if (ret == OPUS_OK) {
enc->frame_size = compute_frame_samples(value);
enc->frame_size_request = value;
}
}```
I am trying to play the ogg file created by example program given in this library. But i am getting error. In input file is S16_LE 16 bit@48000 raw sample , and able to play using "cat pcm.raw| aplay -r 48000 -f S16_LE" successfully.
Error opening o4.ogg using the oggvorbis module. The file may be corrupted.
Any guidance will help me.
#include <stdio.h>
#include "opusenc.h"
#define READ_SIZE 256
int main(int argc, char **argv) {
FILE *fin;
OggOpusEnc enc;
OggOpusComments comments;
int error;
fin = fopen("pcm.raw", "rb");
if (!fin) {
fprintf(stderr, "cannot open input file: %s\n", argv[1]);
return 1;
}
comments = ope_comments_create();
ope_comments_add(comments, "ARTIST", "Someone");
ope_comments_add(comments, "TITLE", "Some track");
enc = ope_encoder_create_file("o4.ogg", comments, 48000, 1, 0, &error);
if (!enc) {
fprintf(stderr, "error encoding to file %s: %s\n", argv[2], ope_strerror(error));
ope_comments_destroy(comments);
fclose(fin);
return 1;
}
while (1) {
short buf[2READ_SIZE];
int ret = fread(buf, 2sizeof(short), READ_SIZE, fin);
if (ret > 0) {
ope_encoder_write(enc, buf, ret);
} else break;
}
ope_encoder_drain(enc);
ope_encoder_destroy(enc);
ope_comments_destroy(comments);
fclose(fin);
return 0;
}
I tried many combinations about mono / stereo
everything with mono seems not working perfectly
Mono input => Mono output
Stereo input => Mono output
the only perfect case is
Stereo input => Stereo output
ope_comments_add_picture_from_memory()
has a size_t
argument, but does not include <stddef.h>
:
Line 252 in 0130afa
This breaks building libopusenc with the musl C library, which is very strict about including headers.
I try to use opusenc for converting a pcm to ogg file, so I modified the sampling rate and the number of channels in the opusenc_example code to the real value of the pcm. And use the opusenc_example to make convert.
But the duration of this ogg file is half of the output of the tool, and it sounds faster than normal, Can anyone help me?
The format of pcm file:
sampling rate: 8000
channels: 1
(1) ----------opusenc_example------------------
#include <stdio.h>
#include "opusenc.h"
#define READ_SIZE 256
int main(int argc, char **argv) {
FILE *fin;
OggOpusEnc *enc;
OggOpusComments *comments;
int error;
if (argc != 3) {
fprintf(stderr, "usage: %s <raw pcm input> <Ogg Opus output>\n", argv[0]);
return 1;
}
fin = fopen(argv[1], "rb");
if (!fin) {
fprintf(stderr, "cannot open input file: %s\n", argv[1]);
return 1;
}
comments = ope_comments_create();
ope_comments_add(comments, "ARTIST", "Someone");
ope_comments_add(comments, "TITLE", "Some track");
enc = ope_encoder_create_file(argv[2], comments, **8000, 1, 0**, &error);
if (!enc) {
fprintf(stderr, "error encoding to file %s: %s\n", argv[2], ope_strerror(error));
ope_comments_destroy(comments);
fclose(fin);
return 1;
}
while (1) {
short buf[2*READ_SIZE];
int ret = fread(buf, 2*sizeof(short), READ_SIZE, fin);
if (ret > 0) {
ope_encoder_write(enc, buf, ret);
} else break;
}
ope_encoder_drain(enc);
ope_encoder_destroy(enc);
ope_comments_destroy(comments);
fclose(fin);
return 0;
}
./opusenc_example 8k16bits_1chan.pcm example_out.opus
(2) opusenc 8k16bits_1chan.pcm tool_out.opus --raw-rate 8000 --raw-chan 1 --raw
here is the pcm file.
pcm.zip
Hi,
I was trying to build the documentation (because I did not see it online, as indicated in README.md).
I encountered two issues. The first was a warning about @HAVE_DOT@
and the second is that nothing appeared in the documentation.
@HAVE_DOT@
When I run doxygen from the doc
directory, I get this warning:
doc$ doxygen
warning: argument '@HAVE_DOT@' for option HAVE_DOT is not a valid boolean value
Using the default: NO!
This seems to be caused by the line (in Doxyfile.in)
HAVE_DOT = @HAVE_DOT@
Is this line correct? Or did I misconfigure something? I'm using doxygen version 1.8.18.
From what I can see, it looks like the other instances of @variable@
in Doxyfile.in are replaced in the Makefile. @HAVE_DOT@
is not.
No Content
When I look at the documentation that is produced, it seems that nothing is documented. Here's what I see when I click on the 'Encoding Options' on the Main Page:
Is this what you would have expected? I see a similar issue with the OpusFile documentation on the opus-codec.org website, so perhaps there is a common configuration issue?
Cheers,
Matthew
pkgconfig installs opus.h
in ${includedir}/opus:
https://github.com/xiph/opus/blob/652c4559f593d3aad78bd5c85a216eeae7859429/opus.pc.in#L16
Therefore, the correct include path is:
#include <opus/opus.h>
instead of:
Line 57 in 0130afa
Single-file reproducer, not sure if I'm using libopusenc incorrectly or if this is a bug.
Steps to reproduce:
I'm using libopusenc, libogg, libopus etc from their respective HEADs
ope_encoder_create_callbacks()
segfaults if the comments
parameter is NULL
:
int ope_error;
OggOpusEnc* enc = ope_encoder_create_callbacks(&ope_callbacks, this, NULL, 48000, 2, 0, &ope_error);
Turned out ope_comments_create()
needs to be called before:
int ope_error;
OggOpusComments* comments = ope_comments_create();
OggOpusEnc* enc = ope_encoder_create_callbacks(&ope_callbacks, this, comments, 48000, 2, 0, &ope_error);
Compile the library using MSVC 2019, see warning:
libopusenc\src\unicode_support.c(44,56): warning C4312: 'type cast': conversion from 'int' to 'wchar_t *' of greater size
The malloc function is used without including its definition. Including "stdlib.h" results in no warning.
I tried to get frame duration by calling ope_encoder_ctl
, but this call ended up with an errorCode=OPE_UNIMPLEMENTED (-15). But as far as I can see this operation was long ago implemented in libopus. Why it is not available in libopusenc?
Code example:
opus_int32 frameSize;
int errorCode = ope_encoder_ctl(encoder_, OPUS_GET_EXPERT_FRAME_DURATION(&frameSize));
Libs versions:
libopus - v1.3.1
libopusenc - master (commit 6e0a98c)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.