Use mutagen for file metadata and support AAC files.

sample-track
Ben Niemann 2020-02-16 12:54:59 +01:00
parent 98f34ea4b1
commit 583b3d7910
6 changed files with 35 additions and 15 deletions

View File

@ -166,6 +166,7 @@ def configure(ctx):
pip_mgr.check_package(RUNTIME, 'toposort')
pip_mgr.check_package(RUNTIME, 'urwid')
pip_mgr.check_package(RUNTIME, 'fastjsonschema')
pip_mgr.check_package(RUNTIME, 'mutagen', version='1.44.0')
pip_mgr.check_package(BUILD, 'cssutils')
pip_mgr.check_package(BUILD, 'Cython', version='0.29.6')
pip_mgr.check_package(BUILD, 'Jinja2')

View File

@ -29,9 +29,7 @@ import subprocess
import time as time_lib
from typing import Any, Optional, Callable, Iterator
import eyed3.core
import eyed3.mimetype
import eyed3.mp3
import mutagen
import numpy
from noisicaa import audioproc
@ -145,6 +143,10 @@ class SampleReader(object):
class SndFileReader(SampleReader):
mime_types = {
'audio/x-wav',
}
def __init__(self, path: str) -> None:
super().__init__()
@ -164,18 +166,20 @@ class SndFileReader(SampleReader):
return self.__sf.read_samples(count)
class Mp3Reader(SampleReader):
class FFMpegReader(SampleReader):
mime_types = {
'audio/mpeg',
'audio/x-hx-aac-adts',
}
def __init__(self, path: str) -> None:
super().__init__()
mp3 = eyed3.core.load(path)
info = mutagen.File(path).info
self.sample_rate = mp3.info.sample_freq
self.num_samples = int(mp3.info.time_secs * mp3.info.sample_freq)
if mp3.info.mode == eyed3.mp3.headers.MODE_MONO:
self.num_channels = 1
else:
self.num_channels = 2
self.sample_rate = info.sample_rate
self.num_samples = int(info.length * info.sample_rate)
self.num_channels = info.channels
cmd = ['/usr/bin/ffmpeg', '-nostdin', '-y', '-i', path, '-f', 'f32le', '-']
self.__proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
@ -197,12 +201,17 @@ class Mp3Reader(SampleReader):
@contextlib.contextmanager
def open_sample(path: str) -> Iterator[SampleReader]:
mtype = eyed3.mimetype.guessMimetype(path)
mtype = subprocess.check_output(
['/usr/bin/file', '--mime-type', '--brief', path]).decode('ascii').strip()
reader = None # type: SampleReader
if mtype in eyed3.mp3.MIME_TYPES:
reader = Mp3Reader(path)
else:
if mtype in SndFileReader.mime_types:
reader = SndFileReader(path)
elif mtype in FFMpegReader.mime_types:
reader = FFMpegReader(path)
else:
raise SampleLoadError("Unsupported file type '%s'" % mtype)
try:
yield reader
finally:

View File

@ -166,6 +166,15 @@ class SampleTrackTest(base_track_test.TrackTestMixin, unittest.AsyncTestCase):
os.path.join(unittest.TESTDATA_DIR, 'future-thunder1.mp3'))
self.assertEqual(track.samples[0].time, audioproc.MusicalTime(1, 4))
async def test_create_sample_aac(self):
track = await self._add_track()
with self.project.apply_mutations('test'):
track.create_sample(
audioproc.MusicalTime(1, 4),
os.path.join(unittest.TESTDATA_DIR, 'future-thunder1.aac'))
self.assertEqual(track.samples[0].time, audioproc.MusicalTime(1, 4))
async def test_delete_sample(self):
track = await self._add_track()
with self.project.apply_mutations('test'):

BIN
testdata/future-thunder1.aac vendored Normal file

Binary file not shown.

1
testdata/wscript vendored
View File

@ -24,6 +24,7 @@ def build(ctx):
ctx.static_file('kick-gettinglaid.wav')
ctx.static_file('future-thunder1.wav')
ctx.static_file('future-thunder1.mp3')
ctx.static_file('future-thunder1.aac')
ctx.static_file('test1.wav')
ctx.static_file('symbol.svg')
ctx.rendered_csound('kick.csnd')