Coder Social home page Coder Social logo

teampyogg / pyogg Goto Github PK

View Code? Open in Web Editor NEW
59.0 5.0 25.0 8.26 MB

Simple OGG Vorbis, Opus and FLAC bindings for Python

License: The Unlicense

Python 99.95% Makefile 0.05%
audio python python3 python2 ogg-vorbis flac opus ogg-opus ogg-flac pypi pip

pyogg's Introduction

PyOgg

Build Status Documentation Status

PyOgg provides Python bindings for Xiph.org’s Opus, Vorbis and FLAC audio file formats as well as their Ogg container format.

PyOgg:

  • Reads and streams Opus, Vorbis, and FLAC audio formats in their standard file format (that is, from within Ogg containers).

  • Writes Opus files (that it, Opus-formatted packets into Ogg containers)

  • Reads and writes Opus-formatted packets (transported, for example, via UDP)

Further, should you wish to have still lower-level access, PyOgg provides ctypes interfaces that give direct access to the C functions and datatypes found in the libraries.

Under Windows, PyOgg comes bundled with the required dynamic libraries (DLLs) in the Windows Wheel distributions.

Under macOS, the required libraries can be easily installed using Homebrew.

PyOgg is not capable of playing audio, however, you can use Python audio libraries such as simpleaudio, sounddevice, or PyOpenAL to play audio. PyOpenAL even offers 3D playback.

For more detail, including installation instructions, please see the documentation at Read the Docs.

Building the Docs

If you are unable to find the documentation at Read the Docs, you may build the documentation yourself. First, clone this repository and from within the repository's directory, install PyOgg in editable mode using:

pip install -e .

Building the documentation requires Sphinx and the Read the Docs theme:

pip install sphinx
pip install sphinx-rtd-theme

Then, enter the docs directory and run:

make html

This will produce a docs/_build/html directory. Open the file index.html to browse the documentation.

pyogg's People

Contributors

gudvinr avatar iojon avatar mattgwwalker avatar pmiddend avatar zuzu-typ avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pyogg's Issues

ImportError: cannot import name 'OpusEncoder' from 'pyogg'

Hi,

I am on Windows 10 and followed the instructions for installing PyOgg.
However, everytime I attempt to use it, I am greeted with this error:

ImportError: cannot import name 'OpusEncoder' from 'pyogg'

I installed it the normal way using pip install in an Anaconda environment.
Any help would be appreciated.

Infinite loop when reading from an opus file

We are encountering an infinite loop when a song is close to its end. We load the song from an opus file. I have debugged the code and saw that you have a while True loop that only breaks if:

samples_read.value*self.channels*2 + ns >= PYOGG_STREAM_BUFFER_SIZE

However, it might be the case that this is never fulfilled. What if there's just not enough data to fill another buffer completely?

Docs: include simple oneliner for apt-get install of common dependencies on Linux

Firstly, thank you for open-sourcing these great tools!

We're using them do load training data for training Speech-to-Text models at Coqui STT :)

I was using pyogg from a script in a new Ubuntu 18.04 environment, I got the following AttributeError:

AttributeError: module 'pyogg.opus' has no attribute 'op_open_file'

Looking through the list of dependencies on the docs, it wasn't immediately obvious to me what to install. It turned out the solution was to install libopusfile0.

Hindsight is 20-20, and I now see in docs the bulleted list under Linux OpusFile. I'd suggest (as with the MacOs example), a simple oneline install command to include for linux. It took me about 30 minutes to figure out what the missing lib was, and for most distros the packages are named similarly enough to make that debugging faster.

AudioFile base class

There is common code that has been copy-pasted in OpusFile, VorbisFile, and FlacFile.

This common code should be extracted into a common base class (AudioFile).

The tests for those three classes also have common code, which should also be cleaned up.

Windows Libraries

Hi Zuzu-Typ,

I've been developing on a Mac up until now, and all has gone well with the Ogg and Opus libraries provided by homebrew. I'm now testing on Windows.

When I installed PyOgg, I did not get any DLLs in the install, as was indicated in the README. (I'm using an AWS Instance of Windows Server 2019 for testing.)

Should the libraries have been included with "pip install pyogg"?

I have now compiled DLLs for Ogg and Opus, but I'm finding producing a DLL for OpusFile a challenge. I see that you contributed a pull request to the official OpusFile repository, but that it wasn't accepted. How did you get around the OpenSSL issues?

Regards,

Matthew

.

Please close.

Documentation: Add vorbis example

In the examples directory there is now an example Vorbis file and code that plays that file.

The example should be added into the documentation.

The Opus libraries weren't found or couldn't be loaded

I use anaconda with python3.6 32bit. platform.architecture()=('32bit', 'WindowsPE')
used pip install pyogg and successfully installed pyogg-0.6.9a1.
In anaconda3\Lib\site-packages\pyogg, i can see those dlls.
image

The error:
C:\Users\YANG.LEI\AppData\Local\Continuum\anaconda3\python.exe
...
file_ = OpusFile(path)
File "C:\Users\YANG.LEI\AppData\Local\Continuum\anaconda3\lib\site-packages\pyogg_init_.py", line 238, in init
raise PyOggError("The Opus libraries weren't found or couldn't be loaded (maybe you're trying to use 64bit libraries with 32bit Python?)")
pyogg.ogg.PyOggError: The Opus libraries weren't found or couldn't be loaded (maybe you're trying to use 64bit libraries with 32bit Python?)

But I'm sure both my python and pyogg is 32bit(when try to install the downloaded 64bit whl it gave me error and exited).

Creating a Wheel for macOS

I've been struggling for most of today to create a PyOgg wheel for macOS.

I cannot work out how to specify a path to ctypes.util.find_library() under macOS. As a consequence, I can't work out how to replicate the current approach (working under Windows) of adding DLLs to the directory containing the Python source files.

I've asked the question on Stack Overflow but if you have any suggestions, I'd love to hear them!

Cheers,

Matthew

AttributeError: module 'pyogg.opus' has no attribute 'opus_int32'

I'm unable to import OpusEncoder using the current master (3783343):

Traceback (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/kyle/projects/bitcast/mumbleice/mumbleice/__main__.py", line 44, in <module>
    icecast = IcecastConnector(cfg['server'], cfg.getint('port'),
  File "/home/kyle/projects/bitcast/mumbleice/mumbleice/bot.py", line 78, in __init__
    self.encoder = OpusEncoder()
  File "/home/kyle/projects/bitcast/mumbleice/pyenv/lib/python3.9/site-packages/pyogg/opus_encoder.py", line 20, in __init__
    self.set_max_bytes_per_frame(4000)
  File "/home/kyle/projects/bitcast/mumbleice/pyenv/lib/python3.9/site-packages/pyogg/opus_encoder.py", line 128, in set_max_bytes_per_frame
    self._max_bytes_per_frame = opus.opus_int32(max_bytes)
AttributeError: module 'pyogg.opus' has no attribute 'opus_int32'

Special characters in file name throws error

Specifically the character that can be created on Windows using Alt+0150: '–'. As soon as I rename a file without this the file can be loaded. I tested this both in PyOpenAL and using pyogg.VorbisFile.

This is the error that happens (running in python interactive environment):

>>> pyogg.VorbisFile("50 Cent – Many Men (Wish Death) [Edit].ogg")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\muizz\AppData\Local\Programs\Python\Python38\lib\site-packages\pyogg\__init__.py", line 33, in __init__
raise PyOggError("file couldn't be opened or doesn't exist. Error code : {}".format(error))
pyogg.ogg.PyOggError: file couldn't be opened or doesn't exist. Error code : -1

Admin rights - Read the Docs

@Zuzu-Typ, I'd like to add you into the admin list for PyOgg's documentation on Read the Docs. If you don't already have an account there, would you like to create one and share your username with me? I'll then add you in as an admin.

Cheers,

Matthew

Opening a ogg file crashes

Hello.
When opening an ogg file using the latest pyogg on pypi, i get either a segmentation violation (x86_64, libogg 1.3.3 on Fedora 31), stacktrace:

#0  0x00007ffff7e6e28f in unlink_chunk.isra () from /lib64/libc.so.6
#1  0x00007ffff7e70f71 in _int_malloc () from /lib64/libc.so.6
#2  0x00007ffff7e72f55 in calloc () from /lib64/libc.so.6
#3  0x00007fffea076166 in floor1_unpack () from /lib64/libvorbis.so.0
#4  0x00007fffea074509 in vorbis_synthesis_headerin ()
   from /lib64/libvorbis.so.0
#5  0x00007fffea05a190 in _fetch_headers () from /lib64/libvorbisfile.so.3
#6  0x00007fffea05b0e5 in _ov_open1 () from /lib64/libvorbisfile.so.3
#7  0x00007fffea05bbc3 in ov_open_callbacks () from /lib64/libvorbisfile.so.3
#8  0x00007fffea05bc7c in ov_open () from /lib64/libvorbisfile.so.3
#9  0x00007fffea05bcc1 in ov_fopen () from /lib64/libvorbisfile.so.3
#10 0x00007fffea60eaa8 in ffi_call_unix64 () from /lib64/libffi.so.6
#11 0x00007fffea60e2a4 in ffi_call () from /lib64/libffi.so.6
#12 0x00007fffea622bd0 in _ctypes_callproc ()
   from /usr/lib64/python3.7/lib-dynload/_ctypes.cpython-37m-x86_64-linux-gnu.so
#13 0x00007fffea6233fc in PyCFuncPtr_call ()
   from /usr/lib64/python3.7/lib-dynload/_ctypes.cpython-37m-x86_64-linux-gnu.so
#14 0x00007ffff7bd957c in _PyObject_FastCallKeywords ()
   from /lib64/libpython3.7m.so.1.0
#15 0x00007ffff7bdace9 in call_function () from /lib64/libpython3.7m.so.1.0
#16 0x00007ffff7c16182 in _PyEval_EvalFrameDefault ()
--Type <RET> for more, q to quit, c to continue without paging-- 
   from /lib64/libpython3.7m.so.1.0
#17 0x00007ffff7bc904a in _PyFunction_FastCallDict ()
   from /lib64/libpython3.7m.so.1.0
#18 0x00007ffff7b9d3c6 in _PyObject_Call_Prepend ()
   from /lib64/libpython3.7m.so.1.0
#19 0x00007ffff7bd8163 in slot_tp_init () from /lib64/libpython3.7m.so.1.0
#20 0x00007ffff7bd91d7 in _PyObject_FastCallKeywords ()
   from /lib64/libpython3.7m.so.1.0
#21 0x00007ffff7bdace9 in call_function () from /lib64/libpython3.7m.so.1.0
#22 0x00007ffff7c16182 in _PyEval_EvalFrameDefault ()
   from /lib64/libpython3.7m.so.1.0
#23 0x00007ffff7bc7b40 in _PyEval_EvalCodeWithName ()
   from /lib64/libpython3.7m.so.1.0
#24 0x00007ffff7bc88d9 in PyEval_EvalCodeEx () from /lib64/libpython3.7m.so.1.0
#25 0x00007ffff7c586bb in PyEval_EvalCode () from /lib64/libpython3.7m.so.1.0
#26 0x00007ffff7c996e3 in run_mod () from /lib64/libpython3.7m.so.1.0
#27 0x00007ffff7b745d6 in PyRun_InteractiveOneObjectEx ()
   from /lib64/libpython3.7m.so.1.0
#28 0x00007ffff7b7bf37 in PyRun_InteractiveLoopFlags ()
   from /lib64/libpython3.7m.so.1.0
#29 0x00007ffff7b7bfd8 in PyRun_AnyFileExFlags.cold ()
   from /lib64/libpython3.7m.so.1.0
#30 0x00007ffff7ca1eb1 in pymain_main () from /lib64/libpython3.7m.so.1.0
--Type <RET> for more, q to quit, c to continue without paging--
#31 0x00007ffff7ca205c in _Py_UnixMain () from /lib64/libpython3.7m.so.1.0
#32 0x00007ffff7e0d1a3 in __libc_start_main () from /lib64/libc.so.6
#33 0x000055555555508e in _start ()

Or under Manjaro ARM, libogg 1.3.6 with an corrupt stack:

#0  0x0000007ff7ac8a68 in unlink_chunk.isra () from /usr/lib/libc.so.6
#1  0x0000007ff7acb524 in _int_malloc () from /usr/lib/libc.so.6
#2  0x0000007ff7acd21c in calloc () from /usr/lib/libc.so.6
#3  0x0000007ff6cd8260 in ?? () from /usr/lib/libvorbis.so.0
#4  0x0000007ff6cfe000 in ?? ()

No idea whether they're related, but i would not be surprised. Note that it works under Windows 10 with the same vorbis file, libogg from the pypi wheel (no idea what version that is - no data in the manifest or anywhere).

A typo found as well as my suggestion for style

In File library_loader.py at Line 33, there is a variable called paths written as pahts, which results in uncaught name xxx not defined exception.

Note that such typo should be caught by exception. However, it is simply dropped in File ogg.py at Line 58.

** Please at least print out exceptions rather than drop them. **

Vorbis: Multiple logical bitstreams

PyOgg doesn't currently support Vorbis files with multiple logical bitstreams.

A logical bitstream may have a different number of channels or even a different sampling rate (see https://xiph.org/vorbis/doc/vorbisfile/ov_read.html).

Vorbis files with multiple logical bitstreams could be supported by chaining VorbisFile instances (with say a 'next' attribute that points to the next VorbisFile that would contain the PCM for the next logical bitstream).

A considerable constraint to implementing this was that examples files that demonstrated multiple logical bitstreams couldn't be found or created. Thus, if anyone is impacted by this issue, it would be extremely useful if you could share example Vorbis files that have multiple logical bitstreams.

Note that even Audacity doesn't handle multiple logical bitstreams (see https://wiki.audacityteam.org/wiki/OGG#Importing_multiple_stream_files).

Encoding libraries bindings

Besides already implemented libopusfile/libvorbisfile there is libopusenc and libvorbisenc (vorbisenc.c/vorbisenc.h) which are high-level helper libraries for encoding opus/vorbis streams.

Is this possible to add bindings for them too?

Separating __init__.py into multiple files

Hi Zuzu-Typ,

Would you be open to having __init__.py separated into a number of files, say one file per class?

As it stands, it's a challenge for me to separate the work I do as everything is connected to the one file.

I'm happy to make the changes if you're happy to accept them.

Cheers,

Matthew

Playing a file with PyAudio

Hi there, I am having trouble getting this library to work with pyaudio. I just want to decode an opus file and play it back but no combination of options seems to work. Could you provide an example?

Working with Vorbis

Hello. @Zuzu-Typ. Thank you for your work, your library is my hope.
I just have a little question.
After successfully opening the .mogg with the VorbisFile class, I don't know what to do with the buffer. How do I decode it?
Can you share some hints or links on this stuff?

Thank you

Single-responsibility OggOpusWriter class

I wanted to write an existing opus stream to a new media file. For example from OpusFileStream. It is needed to merge multiple files.
But OggOpusWriter.write only works with pcm stream. That is, it combines the functions of the writer and encoder.

vorbis_encode_init lookup in wrong library

PyOgg is looking for the vorbis_encode_init symbol in the wrong library. It tries to find the function in the libvorbis.so library but the symbol is exported by libvorbisenc.so

$ nm -D /usr/lib/libvorbisenc.so
00000000002b20b8 B __bss_start
                 U calloc
                 w __cxa_finalize
00000000002b20b8 D _edata
00000000002b20c0 B _end
00000000000161a8 T _fini
                 w __gmon_start__
0000000000013ab8 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
                 U malloc
                 U __stack_chk_fail
0000000000015c60 T vorbis_encode_ctl
0000000000015c10 T vorbis_encode_init
0000000000015a00 T vorbis_encode_init_vbr
0000000000014470 T vorbis_encode_setup_init
0000000000015a50 T vorbis_encode_setup_managed
0000000000015930 T vorbis_encode_setup_vbr
                 U vorbis_info_clear

vorbis_block missing a field

Hello.
When debugging the ogg crashes, i found out that your definition of vorbis block is missing a field, namely after localalloc, at least in libvorbis 1.3.6 there's a totaluse c_long field right after, e. g. the relevant portion of the structure definition should be:

                    ("localalloc", c_long),
                    ("totaluse", c_long),
                    ("reap", POINTER(alloc_chain)),

No idea why it was not a problem for the bundled libraries under Windows (version/allocator differences?), but the library works under Windows with the added field as well.

Opening an ogg file results in double-free

I'm trying to open an OGG file not for streaming, but "normally":

VorbisFile("somefile.ogg")

This fails with:

double free or corruption (out)

Using gdb, I found out that it's somewhere below ov_fopen inside the vorbis library.

Are the vorbis bindings outdated maybe? Or just wrong? I tested this using multiple distributions, using the latest version of PyOgg and version 1.3.6 ob libvorbis.

The gdb trace is:

#0  0x00007ffff649fbe0 in raise ()
   from /nix/store/g2yk54hifqlsjiha3szr4q3ccmdzyrdv-glibc-2.27/lib/libc.so.6
#1  0x00007ffff64a0dc1 in abort ()
   from /nix/store/g2yk54hifqlsjiha3szr4q3ccmdzyrdv-glibc-2.27/lib/libc.so.6
#2  0x00007ffff64e12ac in __libc_message ()
   from /nix/store/g2yk54hifqlsjiha3szr4q3ccmdzyrdv-glibc-2.27/lib/libc.so.6
#3  0x00007ffff64e749a in malloc_printerr ()
   from /nix/store/g2yk54hifqlsjiha3szr4q3ccmdzyrdv-glibc-2.27/lib/libc.so.6
#4  0x00007ffff64e83e0 in _int_free ()
   from /nix/store/g2yk54hifqlsjiha3szr4q3ccmdzyrdv-glibc-2.27/lib/libc.so.6
#5  0x00007fffeb173c37 in vorbis_staticbook_destroy ()
   from /nix/store/a89n6j27jd97wzywkzxfq36zy222krfc-libvorbis-1.3.6/lib/libvorbis.so
#6  0x00007fffeb15da05 in vorbis_synthesis_init ()
   from /nix/store/a89n6j27jd97wzywkzxfq36zy222krfc-libvorbis-1.3.6/lib/libvorbis.so
#7  0x00007fffead1e140 in _fetch_and_process_packet.constprop.14 ()
   from /nix/store/a89n6j27jd97wzywkzxfq36zy222krfc-libvorbis-1.3.6/lib/libvorbisfile.so
#8  0x00007fffead22c28 in ov_read_filter ()
   from /nix/store/a89n6j27jd97wzywkzxfq36zy222krfc-libvorbis-1.3.6/lib/libvorbisfile.so
#9  0x00007fffead23011 in ov_read ()

Multiple definitions of library functions

@Zuzu-Typ mypy popped up with an error around the definition of oggpack_writeinit() in ogg.py. It seems as though we might have a copy-paste error perhaps?

Would you mind having a look at it? Specifically, the issues are around lines 471-490.

To me it seems as though the function has been defined four times, and that possibly it just requires that the python function names are corrected and their calls to the ogg library corrected too so that they match the argument and return type definitions above them. Do you agree? Or is there some magic going on here that I don't understand?

Cheers,

Matthew

libvorbisenc missing in Windows

Hi Zuzu-Typ,

From the work I did on the build process for wheels (#39), I noticed that the current Windows wheels are missing libvorbisenc.dll. I suspect that they were just forgotten :o) but it might be worth adding them into the new pyogg/libs directory. The setup.py file is ready for them as soon as they're added.

Cheers,

Matthew

License details

@Zuzu-Typ I see that you've added license details into the file opus_file.py.

That file only defines the Python class OpusFile (like opus_buffered_encoder.py defines OpusBufferedEncoder).

The actual C-library interface to Opusfile can be found in opus.py. Did you mean for the Opusfile and OpenSSL licenses to be inside the file opus.py? That would match the other license locations.

On Windows, non-ascii path breaks VorbisFile

Hello.
When passing a path to VorbisFile and the path contains a non-ascii character, on Windows it results in a -1 error code from the C library. It would seem that vorbisfile and friends do not expect UTF-8 encoded strings, at least not on Windows.

import error on python3.7

I cannot import the current version of PyOgg==0.6.5a1:

Python 3.7.2 (default, Jan 10 2019, 23:51:51) 
[GCC 8.2.1 20181127] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyogg
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.7/site-packages/pyogg/__init__.py", line 8, in <module>
  from . import opus
File "/usr/lib/python3.7/site-packages/pyogg/opus.py", line 724, in <module>
  libopusfile.opus_head_parse.restype = c_int
File "/usr/lib/python3.7/ctypes/__init__.py", line 369, in __getattr__
  func = self.__getitem__(name)
File "/usr/lib/python3.7/ctypes/__init__.py", line 374, in __getitem__
  func = self._FuncPtr((name_or_ordinal, self))
AttributeError: python: undefined symbol: opus_head_parse

Continuous Integration

@Zuzu-Typ, I have set up basic continuous integration using Travis CI. All the tests are passing for both a macOS and a Windows environment.

Do you have access to the Travis CI configuration? Assuming you do, if you have the time, do you have any comments on the set up? Would you do anything differently?

Cheers,

Matthew

Flac tests failing

The flac tests are failing when only they are run from the root directory (that is, not the tests directory). They are not failing when run as part of the test suite.

Integration with Read the Docs

Hi Zuzu-Typ,

I merged in pull request #39 and started with the process of registering the project with Read the Docs, however it appears I lack the permissions required.

Would you prefer to go through the process yourself? Otherwise, if I understand correctly, you'd need to grant me Admin-level access to the project, as only Admins have the ability to manage webhooks, which Read the Docs depends on.

If you'd prefer not to give me Admin-level access, you can go through the process yourself. You'll need to set up an account with Read the Docs and follow their instructions.

Cheers,

Matthew

undefined symbol: FLAC__VERSION_STRING

Under Linux, with PyOgg 0.6.5a1 and libflac 1.3.2 installed, I get the following exception:

    from pyogg import OpusFile
  File "/home/kim/.local/lib64/python3.6/site-packages/pyogg/__init__.py", line 11, in <module>
    from . import flac
  File "/home/kim/.local/lib64/python3.6/site-packages/pyogg/flac.py", line 149, in <module>
    libflac.FLAC__VERSION_STRING.restype = c_char_p
  File "/usr/lib64/python3.6/ctypes/__init__.py", line 361, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib64/python3.6/ctypes/__init__.py", line 366, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /usr/lib/python-exec/python3.6/python: undefined symbol: FLAC__VERSION_STRING

This doesn't happen with PyOgg 0.6.4a1, but that is because in versions before 0.6.5a1 libflac wasn't detected at all.

Tested with gentoo and Arch linux. It looks like the definitions in flac.py don't match the content of libflac's format.h

OpusFileStream issue

Hi,

I wrote a small example of the use of OpusFileStream. It loads an OggOpus file using both OpusFile and OpusFileStream. It then does a sample-by-sample comparison to ensure that the two techniques produce the same output.

Unfortunately, it appears that the two techniques don't always produce the same result.

Running on the demo file examples/left-right-demo-5s.opus, everything appears to be well:

Read 240000 samples from OpusFile (in 43.1 milliseconds).
Read 240000 samples from the OpusFileStream
(in 126 reads averaging 0.41 milliseconds each).
OpusFileStream data was identical to OpusFile data.

However when I tried it on a much larger Opus file (2.2MB), the two techniques did not produce the same result:

Read 8375296 samples from OpusFile (in 1467.7 milliseconds).
OpusFileStream data was NOT identical to OpusFile data.
Read 449928 samples from the OpusFileStream
(in 234 reads averaging 0.42 milliseconds each).

I have not yet committed the example. I'll have a look into the implementation of OpusFileStream to see if I can resolve the issue. If you're interested, below is the example/test code I was using:

"""Reads an Ogg-Opus file using OpusFile and OpusFileStream.

Reads an Ogg-Opus file using OpusFileStream and compares it to the
results of reading it with OpusFile.  Gives timing information for the
two approaches.

A typical output:

Read 240000 samples from OpusFile (in 43.1 milliseconds).
Read 240000 samples from the OpusFileStream
(in 126 reads averaging 0.41 milliseconds each).
OpusFileStream data was identical to OpusFile data.

"""

import time

import numpy
import pyogg

# Specify a file to process
opus_file_filename = "/Users/matthew/Desktop/VirtualChoir/Sounds/psallite.opus"
opus_file_stream_filename = "/Users/matthew/Desktop/VirtualChoir/Sounds/psallite.opus"
#opus_file_filename = "left-right-demo-5s.opus"
#opus_file_stream_filename = "left-right-demo-5s.opus"

# Open the file using OpusFile, which reads the entire file
# immediately and places it into an internal buffer.
start_time = time.time()
opus_file = pyogg.OpusFile(opus_file_filename)
end_time = time.time()
duration = (end_time-start_time)*1000
array = opus_file.as_array()
array_index = 0
print("Read {:d} samples from OpusFile (in {:.1f} milliseconds).".format(
   len(array),
   duration
))

# Open the file using OpusFileStream, which does not read the entire
# file immediately.
stream = pyogg.OpusFileStream(opus_file_stream_filename)

# Loop through the OpusFileStream until we've read all the data
samples_read = 0
identical = True
times = []
while True:
   # Read the next part of the stream
   start_time = time.time()
   buf = stream.get_buffer_as_array()
   end_time = time.time()
   duration = (end_time-start_time)*1000
   times.append(duration)

   # Check if we've reached the end of the stream
   if buf is None:
       break

   # Increment the number of samples read
   samples_read += len(buf)
   
   # Check we've not read too much data from the stream
   if array_index+len(buf) > len(array):
       print("OpusFileStream data was identical to OpusFile data,\n"+
             "however there was more data in the OpusFileStream than\n"+
             "in the OpusFile.")
       identical = False
       break

   # Compare the stream with the OpusFile data.  (They should be
   # identical.)
   comparison = array[array_index:array_index+len(buf)] == buf
   if not numpy.all(comparison):
       print("OpusFileStream data was NOT identical to OpusFile data.")
       identical = False
       break

   # Move the OpusFile index along
   array_index += len(buf)

avg_time = numpy.mean(times)
print(
   ("Read {:d} samples from the OpusFileStream\n"+
    "(in {:d} reads averaging {:.2f} milliseconds each).").format(
        samples_read,
        len(times),
        avg_time
    )
)

if identical == False:
   # We've finished our work here
   pass
elif array_index == len(array):
   # We completed the comparison successfully.
   print("OpusFileStream data was identical to OpusFile data.")
else:
   # There was remaining data
   print("OpusFileStream data was identical to OpusFile data,\n"+
         "however there was more data in the OpusFile than\n"+
         "in the OpusFileStream.")

Typing and MyPy

@Zuzu-Typ I'm currently still fighting to work out what the issue is in Windows before committing #50.

As a debugging tool I've started adding type information (which can be processed by mypy, a static type checker). Adding the type information can improve the documentation and helps programmers know what they should be passing to a given function. Adding type information also apparently has negligible impact on performance.

Do you have any negative thoughts on adding the type information? If you don't have any issues then I'll keep adding it in as it's proving helpful. It may then form a part of pull request #50.

Cheers,

Matthew

Problems reading opus files

Hi @Zuzu-Typ ,

Many thanks for your library, it seems to be working, but I am facing some issues.
I managed to successfully load the library on Ubuntu-18.04 after running these commands (some of them may be redundant)

pip install PyOgg
conda install -c anaconda libopus
apt install libopus-dev
apt install libopusfile0

After that I could open and listen to an opus file like this:

import pyogg
import numpy as np
from IPython.display import Audio

file = pyogg.OpusFile("detodos.opus")

wav = []
c = 0

for _ in file.buffer:
    wav.append(_)
    c+=1
    if c > file.buffer_length:
        break
        
wav = np.array(wav)
Audio(wav, rate=file.frequency)

Looks like there are a few problems

  • Looks like if I just iterate over the buffer without breaking, there is an infinite loop somewhere
  • The audio should be ~2.5s long, but when I listen to it, it is ~5s long and the second half is filled with some loud artefacts

Please tell if I am doing something wrong!

as_array() method for OpusFile is not available

Hi!

I create OpusFile instance like this:

import pyogg

opus_file = pyogg.OpusFile('file.opus')

But call opus_file.as_array() throws this exception:

AttributeError: 'OpusFile' object has no attribute 'as_array'

I work on Ubuntu 18.04, before steps above I installed libopusfile-dev.

Is this the expected behavior?

Problem loading libFLAC on Linux

Looks like a great project! It looks like there's a bug loading the FLAC library on Linux, though -- with a case-sensitive filesystem, it can't load libFLAC when it's looking for libflac. I've got it working by replacing this bit of flac.py:

libflac = ExternalLibrary.load("flac", tests = [lambda lib: hasattr(lib, "FLAC__EntropyCodingMethodTypeString")])

....with:

if sys.platform == "win32":
    libflac = ExternalLibrary.load("flac", tests = [lambda lib: hasattr(lib, "FLAC__EntropyCodingMethodTypeString")])
else:
    libflac = ExternalLibrary.load("FLAC", tests = [lambda lib: hasattr(lib, "FLAC__EntropyCodingMethodTypeString")])

...but maybe the correct fix would just be to capitalise the library name for all platforms given that win32 is case-insensitive?

OpusEncoder and OpusBufferedEncoder Interfaces

OpusEncoder is currently the base class for OpusBufferedEncoder.

Naturally, they should both have an encode() method. However the two classes return different results. OpusEncoder returns a single encoded frame, while OpusBufferedEncoder may return multiple encoded frames.

Their interfaces need to be tidied up. Perhaps the direct-inheritance should be replaced with a common base class.

Problem with read ogg file

I met another problem when reading ogg file. (with master branch on github this time.)

Simply run:

import pyogg
pyogg.VorbisFile('./test.ogg')

It turns out:

python3: malloc.c:3722: _int_malloc: Assertion `(unsigned long) (size) >= (unsigned long) (nb)' failed.
Aborted (core dumped)

Seems like there is something wrong with memory manipulation in C code, which would be a big trouble.

The ogg file was generated via online recording with Firefox browser. See the attachment.
test.zip

Note that it could be converted to wave file by ffmpeg correctly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.