Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/extern
diff options
context:
space:
mode:
authorJörg Müller <nexyon@gmail.com>2021-08-30 23:36:02 +0300
committerJörg Müller <nexyon@gmail.com>2021-09-18 22:45:33 +0300
commitbdbc7e12a02e15ad7265dfc1ac21fb6d0016308f (patch)
treee9b967deb25f77eef348786f5cd22524eef0ec20 /extern
parent970c928f27106b26ec7cf6afa2316c60384ab4f1 (diff)
Audaspace: added audio file streams functionality.
On the blender side this commit fixes importing video files with audio and video streams that do not share the same start time and duration. Differential Revision: https://developer.blender.org/D12353
Diffstat (limited to 'extern')
-rw-r--r--extern/audaspace/CMakeLists.txt6
-rw-r--r--extern/audaspace/bindings/C/AUD_PlaybackManager.h2
-rw-r--r--extern/audaspace/bindings/C/AUD_Sound.cpp42
-rw-r--r--extern/audaspace/bindings/C/AUD_Sound.h27
-rw-r--r--extern/audaspace/bindings/C/AUD_Special.cpp8
-rw-r--r--extern/audaspace/bindings/C/AUD_Special.h2
-rw-r--r--extern/audaspace/bindings/C/AUD_Types.h14
-rw-r--r--extern/audaspace/bindings/python/PySound.cpp12
-rw-r--r--extern/audaspace/include/IReader.h6
-rw-r--r--extern/audaspace/include/file/File.h23
-rw-r--r--extern/audaspace/include/file/FileInfo.h42
-rw-r--r--extern/audaspace/include/file/FileManager.h24
-rw-r--r--extern/audaspace/include/file/IFileInput.h24
-rw-r--r--extern/audaspace/include/fx/VolumeReader.h2
-rw-r--r--extern/audaspace/plugins/ffmpeg/FFMPEG.cpp18
-rw-r--r--extern/audaspace/plugins/ffmpeg/FFMPEG.h6
-rw-r--r--extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp169
-rw-r--r--extern/audaspace/plugins/ffmpeg/FFMPEGReader.h42
-rw-r--r--extern/audaspace/plugins/libsndfile/SndFile.cpp14
-rw-r--r--extern/audaspace/plugins/libsndfile/SndFile.h6
-rw-r--r--extern/audaspace/plugins/libsndfile/SndFileReader.cpp15
-rw-r--r--extern/audaspace/plugins/libsndfile/SndFileReader.h12
-rw-r--r--extern/audaspace/src/file/File.cpp20
-rw-r--r--extern/audaspace/src/file/FileManager.cpp36
-rw-r--r--extern/audaspace/src/fx/VolumeReader.cpp2
25 files changed, 444 insertions, 130 deletions
diff --git a/extern/audaspace/CMakeLists.txt b/extern/audaspace/CMakeLists.txt
index 1599c03cbad..552ff749512 100644
--- a/extern/audaspace/CMakeLists.txt
+++ b/extern/audaspace/CMakeLists.txt
@@ -152,6 +152,7 @@ set(PUBLIC_HDR
include/devices/ThreadedDevice.h
include/Exception.h
include/file/File.h
+ include/file/FileInfo.h
include/file/FileManager.h
include/file/FileWriter.h
include/file/IFileInput.h
@@ -960,7 +961,10 @@ endif()
if(BUILD_DEMOS)
include_directories(${INCLUDE})
- set(DEMOS audaplay audaconvert audaremap signalgen randsounds dynamicmusic playbackmanager)
+ set(DEMOS audainfo audaplay audaconvert audaremap signalgen randsounds dynamicmusic playbackmanager)
+
+ add_executable(audainfo demos/audainfo.cpp)
+ target_link_libraries(audainfo audaspace)
add_executable(audaplay demos/audaplay.cpp)
target_link_libraries(audaplay audaspace)
diff --git a/extern/audaspace/bindings/C/AUD_PlaybackManager.h b/extern/audaspace/bindings/C/AUD_PlaybackManager.h
index 0fa8171599d..a2f5134602a 100644
--- a/extern/audaspace/bindings/C/AUD_PlaybackManager.h
+++ b/extern/audaspace/bindings/C/AUD_PlaybackManager.h
@@ -39,7 +39,7 @@ extern AUD_API void AUD_PlaybackManager_free(AUD_PlaybackManager* manager);
* Plays a sound through the playback manager, adding it into a category.
* \param manager The PlaybackManager object.
* \param sound The sound to be played.
-* \param catKey The key of the category into which the sound will be added. If it doesn't exist a new one will be creatd.
+* \param catKey The key of the category into which the sound will be added. If it doesn't exist a new one will be created.
*/
extern AUD_API void AUD_PlaybackManager_play(AUD_PlaybackManager* manager, AUD_Sound* sound, unsigned int catKey);
diff --git a/extern/audaspace/bindings/C/AUD_Sound.cpp b/extern/audaspace/bindings/C/AUD_Sound.cpp
index 8c99ce2341f..aa246b9a047 100644
--- a/extern/audaspace/bindings/C/AUD_Sound.cpp
+++ b/extern/audaspace/bindings/C/AUD_Sound.cpp
@@ -94,6 +94,36 @@ AUD_API int AUD_Sound_getLength(AUD_Sound* sound)
return (*sound)->createReader()->getLength();
}
+AUD_API int AUD_Sound_getFileStreams(AUD_Sound* sound, AUD_StreamInfo **stream_infos)
+{
+ assert(sound);
+
+ std::shared_ptr<File> file = std::dynamic_pointer_cast<File>(*sound);
+
+ if(file)
+ {
+ auto streams = file->queryStreams();
+
+ size_t size = sizeof(AUD_StreamInfo) * streams.size();
+
+ if(!size)
+ {
+ *stream_infos = nullptr;
+ return 0;
+ }
+
+ *stream_infos = reinterpret_cast<AUD_StreamInfo*>(std::malloc(size));
+ std::memcpy(*stream_infos, streams.data(), size);
+
+ return streams.size();
+ }
+ else
+ {
+ *stream_infos = nullptr;
+ return 0;
+ }
+}
+
AUD_API sample_t* AUD_Sound_data(AUD_Sound* sound, int* length, AUD_Specs* specs)
{
assert(sound);
@@ -252,6 +282,12 @@ AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size)
return new AUD_Sound(new File(buffer, size));
}
+AUD_API AUD_Sound* AUD_Sound_bufferFileStream(unsigned char* buffer, int size, int stream)
+{
+ assert(buffer);
+ return new AUD_Sound(new File(buffer, size, stream));
+}
+
AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound)
{
assert(sound);
@@ -272,6 +308,12 @@ AUD_API AUD_Sound* AUD_Sound_file(const char* filename)
return new AUD_Sound(new File(filename));
}
+AUD_API AUD_Sound* AUD_Sound_fileStream(const char* filename, int stream)
+{
+ assert(filename);
+ return new AUD_Sound(new File(filename, stream));
+}
+
AUD_API AUD_Sound* AUD_Sound_sawtooth(float frequency, AUD_SampleRate rate)
{
return new AUD_Sound(new Sawtooth(frequency, rate));
diff --git a/extern/audaspace/bindings/C/AUD_Sound.h b/extern/audaspace/bindings/C/AUD_Sound.h
index 53172616781..fc73a31e15c 100644
--- a/extern/audaspace/bindings/C/AUD_Sound.h
+++ b/extern/audaspace/bindings/C/AUD_Sound.h
@@ -36,7 +36,15 @@ extern AUD_API AUD_Specs AUD_Sound_getSpecs(AUD_Sound* sound);
* \return The length of the sound in samples.
* \note This function creates a reader from the sound and deletes it again.
*/
-extern AUD_API int AUD_getLength(AUD_Sound* sound);
+extern AUD_API int AUD_Sound_getLength(AUD_Sound* sound);
+
+/**
+ * Retrieves the stream infos of a sound file.
+ * \param sound The sound to retrieve from which must be a file sound.
+ * \param infos A pointer to a AUD_StreamInfo array that will be allocated and must afterwards be freed by the caller.
+ * \return The number of items in the infos array.
+ */
+extern AUD_API int AUD_Sound_getFileStreams(AUD_Sound* sound, AUD_StreamInfo** stream_infos);
/**
* Reads a sound's samples into memory.
@@ -90,6 +98,15 @@ extern AUD_API AUD_Sound* AUD_Sound_buffer(sample_t* data, int length, AUD_Specs
extern AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size);
/**
+ * Loads a sound file from a memory buffer.
+ * \param buffer The buffer which contains the sound file.
+ * \param size The size of the buffer.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
+ * \return A handle of the sound file.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_bufferFileStream(unsigned char* buffer, int size, int stream);
+
+/**
* Caches a sound into a memory buffer.
* \param sound The sound to cache.
* \return A handle of the cached sound.
@@ -104,6 +121,14 @@ extern AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound);
extern AUD_API AUD_Sound* AUD_Sound_file(const char* filename);
/**
+ * Loads a sound file.
+ * \param filename The filename of the sound file.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
+ * \return A handle of the sound file.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_fileStream(const char* filename, int stream);
+
+/**
* Creates a sawtooth sound.
* \param frequency The frequency of the generated sawtooth sound.
* \param rate The sample rate of the sawtooth sound.
diff --git a/extern/audaspace/bindings/C/AUD_Special.cpp b/extern/audaspace/bindings/C/AUD_Special.cpp
index 5cc33525d1d..1ce25dcd41c 100644
--- a/extern/audaspace/bindings/C/AUD_Special.cpp
+++ b/extern/audaspace/bindings/C/AUD_Special.cpp
@@ -86,7 +86,6 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
info.specs.channels = AUD_CHANNELS_INVALID;
info.specs.rate = AUD_RATE_INVALID;
info.length = 0.0f;
- info.start_offset = 0.0f;
try
{
@@ -96,7 +95,6 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
{
info.specs = convSpecToC(reader->getSpecs());
info.length = reader->getLength() / (float) info.specs.rate;
- info.start_offset = reader->getStartOffset();
}
}
catch(Exception&)
@@ -109,7 +107,7 @@ AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold,
int accumulate, int additive, int square,
- float sthreshold, double samplerate, int* length)
+ float sthreshold, double samplerate, int* length, int stream)
{
Buffer buffer;
DeviceSpecs specs;
@@ -117,7 +115,7 @@ AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
specs.rate = (SampleRate)samplerate;
std::shared_ptr<ISound> sound;
- std::shared_ptr<ISound> file = std::shared_ptr<ISound>(new File(filename));
+ std::shared_ptr<ISound> file = std::shared_ptr<ISound>(new File(filename, stream));
int position = 0;
@@ -247,7 +245,7 @@ AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int sampl
buffer[i * 3] = min;
buffer[i * 3 + 1] = max;
- buffer[i * 3 + 2] = sqrt(power / len); // RMS
+ buffer[i * 3 + 2] = std::sqrt(power / len);
if(overallmax < max)
overallmax = max;
diff --git a/extern/audaspace/bindings/C/AUD_Special.h b/extern/audaspace/bindings/C/AUD_Special.h
index ce51fa2e04e..2f5d13c6fd9 100644
--- a/extern/audaspace/bindings/C/AUD_Special.h
+++ b/extern/audaspace/bindings/C/AUD_Special.h
@@ -37,7 +37,7 @@ extern AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float
float attack, float release, float threshold,
int accumulate, int additive, int square,
float sthreshold, double samplerate,
- int* length);
+ int* length, int stream);
/**
* Pauses a playing sound after a specific amount of time.
diff --git a/extern/audaspace/bindings/C/AUD_Types.h b/extern/audaspace/bindings/C/AUD_Types.h
index c6a96d30d3f..0f95366bc27 100644
--- a/extern/audaspace/bindings/C/AUD_Types.h
+++ b/extern/audaspace/bindings/C/AUD_Types.h
@@ -176,5 +176,17 @@ typedef struct
{
AUD_Specs specs;
float length;
- double start_offset;
} AUD_SoundInfo;
+
+/// Specification of a sound source.
+typedef struct
+{
+ /// Start time in seconds.
+ double start;
+
+ /// Duration in seconds. May be estimated or 0 if unknown.
+ double duration;
+
+ /// Audio data parameters.
+ AUD_DeviceSpecs specs;
+} AUD_StreamInfo;
diff --git a/extern/audaspace/bindings/python/PySound.cpp b/extern/audaspace/bindings/python/PySound.cpp
index 33628307249..2236057e7d2 100644
--- a/extern/audaspace/bindings/python/PySound.cpp
+++ b/extern/audaspace/bindings/python/PySound.cpp
@@ -89,10 +89,11 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
self = (Sound*)type->tp_alloc(type, 0);
if(self != nullptr)
{
- static const char* kwlist[] = {"filename", nullptr};
+ static const char* kwlist[] = {"filename", "stream", nullptr};
const char* filename = nullptr;
+ int stream = 0;
- if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Sound", const_cast<char**>(kwlist), &filename))
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:Sound", const_cast<char**>(kwlist), &filename, &stream))
{
Py_DECREF(self);
return nullptr;
@@ -100,7 +101,7 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
try
{
- self->sound = new std::shared_ptr<ISound>(new File(filename));
+ self->sound = new std::shared_ptr<ISound>(new File(filename, stream));
}
catch(Exception& e)
{
@@ -407,8 +408,9 @@ static PyObject *
Sound_file(PyTypeObject* type, PyObject* args)
{
const char* filename = nullptr;
+ int stream = 0;
- if(!PyArg_ParseTuple(args, "s:file", &filename))
+ if(!PyArg_ParseTuple(args, "s|i:file", &filename, &stream))
return nullptr;
Sound* self;
@@ -418,7 +420,7 @@ Sound_file(PyTypeObject* type, PyObject* args)
{
try
{
- self->sound = new std::shared_ptr<ISound>(new File(filename));
+ self->sound = new std::shared_ptr<ISound>(new File(filename, stream));
}
catch(Exception& e)
{
diff --git a/extern/audaspace/include/IReader.h b/extern/audaspace/include/IReader.h
index f6070b0f23b..c29900ca579 100644
--- a/extern/audaspace/include/IReader.h
+++ b/extern/audaspace/include/IReader.h
@@ -71,12 +71,6 @@ public:
virtual int getPosition() const=0;
/**
- * Returns the start offset the sound should have to line up with related sources.
- * \return The required start offset in seconds.
- */
- virtual double getStartOffset() const { return 0.0;}
-
- /**
* Returns the specification of the reader.
* \return The Specs structure.
*/
diff --git a/extern/audaspace/include/file/File.h b/extern/audaspace/include/file/File.h
index 24745a757e8..ac490acba38 100644
--- a/extern/audaspace/include/file/File.h
+++ b/extern/audaspace/include/file/File.h
@@ -23,9 +23,11 @@
*/
#include "ISound.h"
+#include "FileInfo.h"
#include <string>
#include <memory>
+#include <vector>
AUD_NAMESPACE_BEGIN
@@ -48,6 +50,14 @@ private:
*/
std::shared_ptr<Buffer> m_buffer;
+ /**
+ * The index of the stream within the file if it contains multiple.
+ * The first audio stream in the file has index 0 and the index increments by one
+ * for every other audio stream in the file. Other types of streams in the file
+ * do not count.
+ */
+ int m_stream;
+
// delete copy constructor and operator=
File(const File&) = delete;
File& operator=(const File&) = delete;
@@ -57,16 +67,25 @@ public:
* Creates a new sound.
* The file is read from the file system using the given path.
* \param filename The sound file path.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
- File(std::string filename);
+ File(std::string filename, int stream = 0);
/**
* Creates a new sound.
* The file is read from memory using the supplied buffer.
* \param buffer The buffer to read from.
* \param size The size of the buffer.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
+ */
+ File(const data_t* buffer, int size, int stream = 0);
+
+ /**
+ * Queries the streams of the file.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
*/
- File(const data_t* buffer, int size);
+ std::vector<StreamInfo> queryStreams();
virtual std::shared_ptr<IReader> createReader();
};
diff --git a/extern/audaspace/include/file/FileInfo.h b/extern/audaspace/include/file/FileInfo.h
new file mode 100644
index 00000000000..53ba99a5f67
--- /dev/null
+++ b/extern/audaspace/include/file/FileInfo.h
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+/**
+ * @file FileInfo.h
+ * @ingroup file
+ * The FileInfo data structures.
+ */
+
+#include "respec/Specification.h"
+
+AUD_NAMESPACE_BEGIN
+
+/// Specification of a sound source.
+struct StreamInfo
+{
+ /// Start time in seconds.
+ double start;
+
+ /// Duration in seconds. May be estimated or 0 if unknown.
+ double duration;
+
+ /// Audio data parameters.
+ DeviceSpecs specs;
+};
+
+AUD_NAMESPACE_END
diff --git a/extern/audaspace/include/file/FileManager.h b/extern/audaspace/include/file/FileManager.h
index 56708607ea6..e19eef65b1c 100644
--- a/extern/audaspace/include/file/FileManager.h
+++ b/extern/audaspace/include/file/FileManager.h
@@ -22,12 +22,14 @@
* The FileManager class.
*/
+#include "FileInfo.h"
#include "respec/Specification.h"
#include "IWriter.h"
#include <list>
#include <memory>
#include <string>
+#include <vector>
AUD_NAMESPACE_BEGIN
@@ -66,18 +68,36 @@ public:
/**
* Creates a file reader for the given filename if a registed IFileInput is able to read it.
* @param filename The path to the file.
+ * @param stream The index of the audio stream within the file if it contains multiple audio streams.
* @return The reader created.
* @exception Exception If no file input can read the file an exception is thrown.
*/
- static std::shared_ptr<IReader> createReader(std::string filename);
+ static std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
/**
* Creates a file reader for the given buffer if a registed IFileInput is able to read it.
* @param buffer The buffer to read the file from.
+ * @param stream The index of the audio stream within the file if it contains multiple audio streams.
* @return The reader created.
* @exception Exception If no file input can read the file an exception is thrown.
*/
- static std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer);
+ static std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
+
+ /**
+ * Queries the streams of a sound file.
+ * \param filename Path to the file to be read.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ static std::vector<StreamInfo> queryStreams(std::string filename);
+
+ /**
+ * Queries the streams of a sound file.
+ * \param buffer The in-memory file buffer.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ static std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
/**
* Creates a file writer that writes a sound to the given file path.
diff --git a/extern/audaspace/include/file/IFileInput.h b/extern/audaspace/include/file/IFileInput.h
index 64074910d13..4a3fe446852 100644
--- a/extern/audaspace/include/file/IFileInput.h
+++ b/extern/audaspace/include/file/IFileInput.h
@@ -23,9 +23,11 @@
*/
#include "Audaspace.h"
+#include "FileInfo.h"
#include <memory>
#include <string>
+#include <vector>
AUD_NAMESPACE_BEGIN
@@ -48,18 +50,36 @@ public:
/**
* Creates a reader for a file to be read.
* \param filename Path to the file to be read.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return The reader that reads the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
- virtual std::shared_ptr<IReader> createReader(std::string filename)=0;
+ virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0)=0;
/**
* Creates a reader for a file to be read from memory.
* \param buffer The in-memory file buffer.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \return The reader that reads the file.
* \exception Exception Thrown if the file specified cannot be read.
*/
- virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer)=0;
+ virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0)=0;
+
+ /**
+ * Queries the streams of a sound file.
+ * \param filename Path to the file to be read.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector<StreamInfo> queryStreams(std::string filename)=0;
+
+ /**
+ * Queries the streams of a sound file.
+ * \param buffer The in-memory file buffer.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer)=0;
};
AUD_NAMESPACE_END
diff --git a/extern/audaspace/include/fx/VolumeReader.h b/extern/audaspace/include/fx/VolumeReader.h
index f7169f4c78b..13b6845e931 100644
--- a/extern/audaspace/include/fx/VolumeReader.h
+++ b/extern/audaspace/include/fx/VolumeReader.h
@@ -67,4 +67,4 @@ public:
virtual void read(int& length, bool& eos, sample_t* buffer);
};
-AUD_NAMESPACE_END
+AUD_NAMESPACE_END \ No newline at end of file
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp b/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
index 3ffe963b2b9..07c0fee691a 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
@@ -35,14 +35,24 @@ void FFMPEG::registerPlugin()
FileManager::registerOutput(plugin);
}
-std::shared_ptr<IReader> FFMPEG::createReader(std::string filename)
+std::shared_ptr<IReader> FFMPEG::createReader(std::string filename, int stream)
{
- return std::shared_ptr<IReader>(new FFMPEGReader(filename));
+ return std::shared_ptr<IReader>(new FFMPEGReader(filename, stream));
}
-std::shared_ptr<IReader> FFMPEG::createReader(std::shared_ptr<Buffer> buffer)
+std::shared_ptr<IReader> FFMPEG::createReader(std::shared_ptr<Buffer> buffer, int stream)
{
- return std::shared_ptr<IReader>(new FFMPEGReader(buffer));
+ return std::shared_ptr<IReader>(new FFMPEGReader(buffer, stream));
+}
+
+std::vector<StreamInfo> FFMPEG::queryStreams(std::string filename)
+{
+ return FFMPEGReader(filename).queryStreams();
+}
+
+std::vector<StreamInfo> FFMPEG::queryStreams(std::shared_ptr<Buffer> buffer)
+{
+ return FFMPEGReader(buffer).queryStreams();
}
std::shared_ptr<IWriter> FFMPEG::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEG.h b/extern/audaspace/plugins/ffmpeg/FFMPEG.h
index 108ba547e0f..fb40ba05573 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEG.h
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEG.h
@@ -52,8 +52,10 @@ public:
*/
static void registerPlugin();
- virtual std::shared_ptr<IReader> createReader(std::string filename);
- virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer);
+ virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
+ virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
+ virtual std::vector<StreamInfo> queryStreams(std::string filename);
+ virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
virtual std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
};
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
index afdc7fcfcc6..de3ca099696 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
@@ -31,6 +31,25 @@ AUD_NAMESPACE_BEGIN
#define FFMPEG_OLD_CODE
#endif
+SampleFormat FFMPEGReader::convertSampleFormat(AVSampleFormat format)
+{
+ switch(av_get_packed_sample_fmt(format))
+ {
+ case AV_SAMPLE_FMT_U8:
+ return FORMAT_U8;
+ case AV_SAMPLE_FMT_S16:
+ return FORMAT_S16;
+ case AV_SAMPLE_FMT_S32:
+ return FORMAT_S32;
+ case AV_SAMPLE_FMT_FLT:
+ return FORMAT_FLOAT32;
+ case AV_SAMPLE_FMT_DBL:
+ return FORMAT_FLOAT64;
+ default:
+ AUD_THROW(FileException, "FFMPEG sample format unknown.");
+ }
+}
+
int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
{
int buf_size = buffer.getSize();
@@ -68,7 +87,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
- m_frame->data[channel] + i * single_size, single_size);
+ m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -109,7 +128,7 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
for(int i = 0; i < m_frame->nb_samples; i++)
{
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
- m_frame->data[channel] + i * single_size, single_size);
+ m_frame->data[channel] + i * single_size, single_size);
}
}
}
@@ -123,13 +142,10 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
return buf_pos;
}
-void FFMPEGReader::init()
+void FFMPEGReader::init(int stream)
{
m_position = 0;
- m_start_offset = 0.0f;
m_pkgbuf_left = 0;
- m_st_time = 0;
- m_duration = 0;
if(avformat_find_stream_info(m_formatCtx, nullptr) < 0)
AUD_THROW(FileException, "File couldn't be read, ffmpeg couldn't find the stream info.");
@@ -137,43 +153,22 @@ void FFMPEGReader::init()
// find audio stream and codec
m_stream = -1;
- double dur_sec = 0;
-
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
{
#ifdef FFMPEG_OLD_CODE
- if(m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+ if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
#else
- if(m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+ if((m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
#endif
+ && (m_stream < 0))
{
- AVStream *audio_stream = m_formatCtx->streams[i];
- double audio_timebase = av_q2d(audio_stream->time_base);
-
- if (audio_stream->start_time != AV_NOPTS_VALUE)
+ if(stream == 0)
{
- m_st_time = audio_stream->start_time;
- }
-
- int64_t ctx_start_time = 0;
- if (m_formatCtx->start_time != AV_NOPTS_VALUE) {
- ctx_start_time = m_formatCtx->start_time;
- }
-
- m_start_offset = m_st_time * audio_timebase - (double)ctx_start_time / AV_TIME_BASE;
-
- if(audio_stream->duration != AV_NOPTS_VALUE)
- {
- dur_sec = audio_stream->duration * audio_timebase;
+ m_stream=i;
+ break;
}
else
- {
- /* If the audio starts after the stream start time, subract this from the total duration. */
- dur_sec = (double)m_formatCtx->duration / AV_TIME_BASE - m_start_offset;
- }
-
- m_stream=i;
- break;
+ stream--;
}
}
@@ -242,10 +237,9 @@ void FFMPEGReader::init()
}
m_specs.rate = (SampleRate) m_codecCtx->sample_rate;
- m_duration = lround(dur_sec * m_codecCtx->sample_rate);
}
-FFMPEGReader::FFMPEGReader(std::string filename) :
+FFMPEGReader::FFMPEGReader(std::string filename, int stream) :
m_pkgbuf(),
m_formatCtx(nullptr),
m_codecCtx(nullptr),
@@ -259,7 +253,7 @@ FFMPEGReader::FFMPEGReader(std::string filename) :
try
{
- init();
+ init(stream);
}
catch(Exception&)
{
@@ -268,7 +262,7 @@ FFMPEGReader::FFMPEGReader(std::string filename) :
}
}
-FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer) :
+FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer, int stream) :
m_pkgbuf(),
m_codecCtx(nullptr),
m_frame(nullptr),
@@ -295,7 +289,7 @@ FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer) :
try
{
- init();
+ init(stream);
}
catch(Exception&)
{
@@ -318,6 +312,51 @@ FFMPEGReader::~FFMPEGReader()
avformat_close_input(&m_formatCtx);
}
+std::vector<StreamInfo> FFMPEGReader::queryStreams()
+{
+ std::vector<StreamInfo> result;
+
+ for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
+ {
+#ifdef FFMPEG_OLD_CODE
+ if(m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+#else
+ if(m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+#endif
+ {
+ StreamInfo info;
+
+ double time_base = av_q2d(m_formatCtx->streams[i]->time_base);
+
+ if(m_formatCtx->streams[i]->start_time != AV_NOPTS_VALUE)
+ info.start = m_formatCtx->streams[i]->start_time * time_base;
+ else
+ info.start = 0;
+
+ if(m_formatCtx->streams[i]->duration != AV_NOPTS_VALUE)
+ info.duration = m_formatCtx->streams[i]->duration * time_base;
+ else if(m_formatCtx->duration != AV_NOPTS_VALUE)
+ info.duration = double(m_formatCtx->duration) / AV_TIME_BASE - info.start;
+ else
+ info.duration = 0;
+
+#ifdef FFMPEG_OLD_CODE
+ info.specs.channels = Channels(m_formatCtx->streams[i]->codec->channels);
+ info.specs.rate = m_formatCtx->streams[i]->codec->sample_rate;
+ info.specs.format = convertSampleFormat(m_formatCtx->streams[i]->codec->sample_fmt);
+#else
+ info.specs.channels = Channels(m_formatCtx->streams[i]->codecpar->channels);
+ info.specs.rate = m_formatCtx->streams[i]->codecpar->sample_rate;
+ info.specs.format = convertSampleFormat(AVSampleFormat(m_formatCtx->streams[i]->codecpar->format));
+#endif
+
+ result.emplace_back(info);
+ }
+ }
+
+ return result;
+}
+
int FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
{
FFMPEGReader* reader = reinterpret_cast<FFMPEGReader*>(opaque);
@@ -368,18 +407,16 @@ void FFMPEGReader::seek(int position)
{
if(position >= 0)
{
- double pts_time_base =
- av_q2d(m_formatCtx->streams[m_stream]->time_base);
+ double pts_time_base = av_q2d(m_formatCtx->streams[m_stream]->time_base);
- uint64_t seek_pts = (((uint64_t)position) / ((uint64_t)m_specs.rate)) / pts_time_base;
+ uint64_t st_time = m_formatCtx->streams[m_stream]->start_time;
+ uint64_t seek_pos = (uint64_t)(position / (pts_time_base * m_specs.rate));
- if(m_st_time != AV_NOPTS_VALUE) {
- seek_pts += m_st_time;
- }
+ if(st_time != AV_NOPTS_VALUE)
+ seek_pos += st_time;
// a value < 0 tells us that seeking failed
- if(av_seek_frame(m_formatCtx, m_stream, seek_pts,
- AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
+ if(av_seek_frame(m_formatCtx, m_stream, seek_pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
{
avcodec_flush_buffers(m_codecCtx);
m_position = position;
@@ -400,7 +437,7 @@ void FFMPEGReader::seek(int position)
if(packet.pts != AV_NOPTS_VALUE)
{
// calculate real position, and read to frame!
- m_position = (packet.pts - m_st_time) * pts_time_base * m_specs.rate;
+ m_position = (packet.pts - (st_time != AV_NOPTS_VALUE ? st_time : 0)) * pts_time_base * m_specs.rate;
if(m_position < position)
{
@@ -430,8 +467,25 @@ void FFMPEGReader::seek(int position)
int FFMPEGReader::getLength() const
{
+ auto stream = m_formatCtx->streams[m_stream];
+
+ double time_base = av_q2d(stream->time_base);
+ double duration;
+
+ if(stream->duration != AV_NOPTS_VALUE)
+ duration = stream->duration * time_base;
+ else if(m_formatCtx->duration != AV_NOPTS_VALUE)
+ {
+ duration = float(m_formatCtx->duration) / AV_TIME_BASE;
+
+ if(stream->start_time != AV_NOPTS_VALUE)
+ duration -= stream->start_time * time_base;
+ }
+ else
+ duration = -1;
+
// return approximated remaning size
- return m_duration - m_position;
+ return (int)(duration * m_codecCtx->sample_rate) - m_position;
}
int FFMPEGReader::getPosition() const
@@ -439,11 +493,6 @@ int FFMPEGReader::getPosition() const
return m_position;
}
-double FFMPEGReader::getStartOffset() const
-{
- return m_start_offset;
-}
-
Specs FFMPEGReader::getSpecs() const
{
return m_specs.specs;
@@ -480,13 +529,11 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
// decode the package
pkgbuf_pos = decode(packet, m_pkgbuf);
- if (packet.pts >= m_st_time) {
- // copy to output buffer
- data_size = std::min(pkgbuf_pos, left * sample_size);
- m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
- buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
- left -= data_size / sample_size;
- }
+ // copy to output buffer
+ data_size = std::min(pkgbuf_pos, left * sample_size);
+ m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
+ buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
+ left -= data_size / sample_size;
}
av_packet_unref(&packet);
}
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
index d613457c220..70f13911eca 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.h
@@ -29,9 +29,11 @@
#include "respec/ConverterFunctions.h"
#include "IReader.h"
#include "util/Buffer.h"
+#include "file/FileInfo.h"
#include <string>
#include <memory>
+#include <vector>
struct AVCodecContext;
extern "C" {
@@ -55,22 +57,6 @@ private:
int m_position;
/**
- * The start offset in seconds relative to the media container start time.
- * IE how much the sound should be delayed to be kept in sync with the rest of the containter streams.
- */
- double m_start_offset;
-
- /**
- * The start time pts of the stream. All packets before this timestamp shouldn't be played back (only decoded).
- */
- int64_t m_st_time;
-
- /**
- * The duration of the audio stream in samples.
- */
- int64_t m_duration;
-
- /**
* The specification of the audio data.
*/
DeviceSpecs m_specs;
@@ -136,6 +122,13 @@ private:
bool m_tointerleave;
/**
+ * Converts an ffmpeg sample format to an audaspace one.
+ * \param format The AVSampleFormat sample format.
+ * \return The sample format as SampleFormat.
+ */
+ AUD_LOCAL static SampleFormat convertSampleFormat(AVSampleFormat format);
+
+ /**
* Decodes a packet into the given buffer.
* \param packet The AVPacket to decode.
* \param buffer The target buffer.
@@ -145,8 +138,9 @@ private:
/**
* Initializes the object.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
*/
- AUD_LOCAL void init();
+ AUD_LOCAL void init(int stream);
// delete copy constructor and operator=
FFMPEGReader(const FFMPEGReader&) = delete;
@@ -156,18 +150,20 @@ public:
/**
* Creates a new reader.
* \param filename The path to the file to be read.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the file specified does not exist or
* cannot be read with ffmpeg.
*/
- FFMPEGReader(std::string filename);
+ FFMPEGReader(std::string filename, int stream = 0);
/**
* Creates a new reader.
* \param buffer The buffer to read from.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the buffer specified cannot be read
* with ffmpeg.
*/
- FFMPEGReader(std::shared_ptr<Buffer> buffer);
+ FFMPEGReader(std::shared_ptr<Buffer> buffer, int stream = 0);
/**
* Destroys the reader and closes the file.
@@ -175,6 +171,13 @@ public:
virtual ~FFMPEGReader();
/**
+ * Queries the streams of a sound file.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector<StreamInfo> queryStreams();
+
+ /**
* Reads data to a memory buffer.
* This function is used for avio only.
* @param opaque The FFMPEGReader.
@@ -198,7 +201,6 @@ public:
virtual void seek(int position);
virtual int getLength() const;
virtual int getPosition() const;
- virtual double getStartOffset() const;
virtual Specs getSpecs() const;
virtual void read(int& length, bool& eos, sample_t* buffer);
};
diff --git a/extern/audaspace/plugins/libsndfile/SndFile.cpp b/extern/audaspace/plugins/libsndfile/SndFile.cpp
index ba4ff24ad68..39335de9a1a 100644
--- a/extern/audaspace/plugins/libsndfile/SndFile.cpp
+++ b/extern/audaspace/plugins/libsndfile/SndFile.cpp
@@ -32,16 +32,26 @@ void SndFile::registerPlugin()
FileManager::registerOutput(plugin);
}
-std::shared_ptr<IReader> SndFile::createReader(std::string filename)
+std::shared_ptr<IReader> SndFile::createReader(std::string filename, int stream)
{
return std::shared_ptr<IReader>(new SndFileReader(filename));
}
-std::shared_ptr<IReader> SndFile::createReader(std::shared_ptr<Buffer> buffer)
+std::shared_ptr<IReader> SndFile::createReader(std::shared_ptr<Buffer> buffer, int stream)
{
return std::shared_ptr<IReader>(new SndFileReader(buffer));
}
+std::vector<StreamInfo> SndFile::queryStreams(std::string filename)
+{
+ return SndFileReader(filename).queryStreams();
+}
+
+std::vector<StreamInfo> SndFile::queryStreams(std::shared_ptr<Buffer> buffer)
+{
+ return SndFileReader(buffer).queryStreams();
+}
+
std::shared_ptr<IWriter> SndFile::createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate)
{
return std::shared_ptr<IWriter>(new SndFileWriter(filename, specs, format, codec, bitrate));
diff --git a/extern/audaspace/plugins/libsndfile/SndFile.h b/extern/audaspace/plugins/libsndfile/SndFile.h
index 61afed1d564..10a7391180f 100644
--- a/extern/audaspace/plugins/libsndfile/SndFile.h
+++ b/extern/audaspace/plugins/libsndfile/SndFile.h
@@ -52,8 +52,10 @@ public:
*/
static void registerPlugin();
- virtual std::shared_ptr<IReader> createReader(std::string filename);
- virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer);
+ virtual std::shared_ptr<IReader> createReader(std::string filename, int stream = 0);
+ virtual std::shared_ptr<IReader> createReader(std::shared_ptr<Buffer> buffer, int stream = 0);
+ virtual std::vector<StreamInfo> queryStreams(std::string filename);
+ virtual std::vector<StreamInfo> queryStreams(std::shared_ptr<Buffer> buffer);
virtual std::shared_ptr<IWriter> createWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate);
};
diff --git a/extern/audaspace/plugins/libsndfile/SndFileReader.cpp b/extern/audaspace/plugins/libsndfile/SndFileReader.cpp
index d2d89814c07..21c733d8117 100644
--- a/extern/audaspace/plugins/libsndfile/SndFileReader.cpp
+++ b/extern/audaspace/plugins/libsndfile/SndFileReader.cpp
@@ -118,6 +118,21 @@ SndFileReader::~SndFileReader()
sf_close(m_sndfile);
}
+std::vector<StreamInfo> SndFileReader::queryStreams()
+{
+ std::vector<StreamInfo> result;
+
+ StreamInfo info;
+ info.start = 0;
+ info.duration = double(getLength()) / m_specs.rate;
+ info.specs.specs = m_specs;
+ info.specs.format = FORMAT_FLOAT32;
+
+ result.emplace_back(info);
+
+ return result;
+}
+
bool SndFileReader::isSeekable() const
{
return m_seekable;
diff --git a/extern/audaspace/plugins/libsndfile/SndFileReader.h b/extern/audaspace/plugins/libsndfile/SndFileReader.h
index 081c29c686c..b4158d9091a 100644
--- a/extern/audaspace/plugins/libsndfile/SndFileReader.h
+++ b/extern/audaspace/plugins/libsndfile/SndFileReader.h
@@ -28,9 +28,12 @@
* The SndFileReader class.
*/
+#include "file/FileInfo.h"
+
#include <string>
#include <sndfile.h>
#include <memory>
+#include <vector>
AUD_NAMESPACE_BEGIN
@@ -96,6 +99,7 @@ public:
/**
* Creates a new reader.
* \param filename The path to the file to be read.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the file specified does not exist or
* cannot be read with libsndfile.
*/
@@ -104,6 +108,7 @@ public:
/**
* Creates a new reader.
* \param buffer The buffer to read from.
+ * \param stream The index of the audio stream within the file if it contains multiple audio streams.
* \exception Exception Thrown if the buffer specified cannot be read
* with libsndfile.
*/
@@ -114,6 +119,13 @@ public:
*/
virtual ~SndFileReader();
+ /**
+ * Queries the streams of a sound file.
+ * \return A vector with as many streams as there are in the file.
+ * \exception Exception Thrown if the file specified cannot be read.
+ */
+ virtual std::vector<StreamInfo> queryStreams();
+
virtual bool isSeekable() const;
virtual void seek(int position);
virtual int getLength() const;
diff --git a/extern/audaspace/src/file/File.cpp b/extern/audaspace/src/file/File.cpp
index 0cdecb03657..5d4bae482d6 100644
--- a/extern/audaspace/src/file/File.cpp
+++ b/extern/audaspace/src/file/File.cpp
@@ -23,23 +23,31 @@
AUD_NAMESPACE_BEGIN
-File::File(std::string filename) :
- m_filename(filename)
+File::File(std::string filename, int stream) :
+ m_filename(filename), m_stream(stream)
{
}
-File::File(const data_t* buffer, int size) :
- m_buffer(new Buffer(size))
+File::File(const data_t* buffer, int size, int stream) :
+ m_buffer(new Buffer(size)), m_stream(stream)
{
std::memcpy(m_buffer->getBuffer(), buffer, size);
}
+std::vector<StreamInfo> File::queryStreams()
+{
+ if(m_buffer.get())
+ return FileManager::queryStreams(m_buffer);
+ else
+ return FileManager::queryStreams(m_filename);
+}
+
std::shared_ptr<IReader> File::createReader()
{
if(m_buffer.get())
- return FileManager::createReader(m_buffer);
+ return FileManager::createReader(m_buffer, m_stream);
else
- return FileManager::createReader(m_filename);
+ return FileManager::createReader(m_filename, m_stream);
}
AUD_NAMESPACE_END
diff --git a/extern/audaspace/src/file/FileManager.cpp b/extern/audaspace/src/file/FileManager.cpp
index f8ef8deb409..7cbc0318f8c 100644
--- a/extern/audaspace/src/file/FileManager.cpp
+++ b/extern/audaspace/src/file/FileManager.cpp
@@ -43,13 +43,13 @@ void FileManager::registerOutput(std::shared_ptr<aud::IFileOutput> output)
outputs().push_back(output);
}
-std::shared_ptr<IReader> FileManager::createReader(std::string filename)
+std::shared_ptr<IReader> FileManager::createReader(std::string filename, int stream)
{
for(std::shared_ptr<IFileInput> input : inputs())
{
try
{
- return input->createReader(filename);
+ return input->createReader(filename, stream);
}
catch(Exception&) {}
}
@@ -57,13 +57,41 @@ std::shared_ptr<IReader> FileManager::createReader(std::string filename)
AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
}
-std::shared_ptr<IReader> FileManager::createReader(std::shared_ptr<Buffer> buffer)
+std::shared_ptr<IReader> FileManager::createReader(std::shared_ptr<Buffer> buffer, int stream)
{
for(std::shared_ptr<IFileInput> input : inputs())
{
try
{
- return input->createReader(buffer);
+ return input->createReader(buffer, stream);
+ }
+ catch(Exception&) {}
+ }
+
+ AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
+}
+
+std::vector<StreamInfo> FileManager::queryStreams(std::string filename)
+{
+ for(std::shared_ptr<IFileInput> input : inputs())
+ {
+ try
+ {
+ return input->queryStreams(filename);
+ }
+ catch(Exception&) {}
+ }
+
+ AUD_THROW(FileException, "The file couldn't be read with any installed file reader.");
+}
+
+std::vector<StreamInfo> FileManager::queryStreams(std::shared_ptr<Buffer> buffer)
+{
+ for(std::shared_ptr<IFileInput> input : inputs())
+ {
+ try
+ {
+ return input->queryStreams(buffer);
}
catch(Exception&) {}
}
diff --git a/extern/audaspace/src/fx/VolumeReader.cpp b/extern/audaspace/src/fx/VolumeReader.cpp
index 627acbac9ef..ac1d4882a87 100644
--- a/extern/audaspace/src/fx/VolumeReader.cpp
+++ b/extern/audaspace/src/fx/VolumeReader.cpp
@@ -57,4 +57,4 @@ void VolumeReader::read(int& length, bool& eos, sample_t* buffer)
buffer[i] = buffer[i] * m_volumeStorage->getVolume();
}
-AUD_NAMESPACE_END
+AUD_NAMESPACE_END \ No newline at end of file