mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 08:39:46 +02:00
Importer functions return a vector of vector of pointers to tracks...
... grouping the channels; rather than one flat vector. OGG, GStreamer and FFmpeg import were written to allow multiple multi-channel tracks; others always imported one group of channels. All of that is reflected in the results returned by the importers, though it makes no difference yet in AudacityProject::AddImportedTracks (where the results are used).
This commit is contained in:
parent
b0c5f42b9a
commit
31d46ae624
@ -4168,7 +4168,6 @@ AudacityProject::AddImportedTracks(const wxString &fileName,
|
||||
{
|
||||
std::vector< std::shared_ptr< Track > > results;
|
||||
|
||||
const auto numTracks = newTracks.size();
|
||||
SelectNone();
|
||||
|
||||
bool initiallyEmpty = mTracks->empty();
|
||||
@ -4177,9 +4176,11 @@ AudacityProject::AddImportedTracks(const wxString &fileName,
|
||||
int i = -1;
|
||||
|
||||
// Must add all tracks first (before using Track::IsLeader)
|
||||
for (auto &uNewTrack : newTracks) {
|
||||
auto newTrack = mTracks->Add(std::move(uNewTrack));
|
||||
results.push_back(Track::Pointer(newTrack));
|
||||
for (auto &group : newTracks) {
|
||||
for (auto &uNewTrack : group) {
|
||||
auto newTrack = mTracks->Add(std::move(uNewTrack));
|
||||
results.push_back(Track::Pointer(newTrack));
|
||||
}
|
||||
}
|
||||
newTracks.clear();
|
||||
|
||||
|
@ -49,6 +49,7 @@ and ImportLOF.cpp.
|
||||
#include <wx/listimpl.cpp>
|
||||
#include "../ShuttleGui.h"
|
||||
#include "../Project.h"
|
||||
#include "../WaveTrack.h"
|
||||
|
||||
#include "ImportPCM.h"
|
||||
#include "ImportMP3.h"
|
||||
@ -538,6 +539,15 @@ bool Importer::Import(const wxString &fName,
|
||||
return true;
|
||||
}
|
||||
|
||||
auto end = tracks.end();
|
||||
auto iter = std::remove_if( tracks.begin(), end,
|
||||
std::mem_fn( &NewChannelGroup::empty ) );
|
||||
if ( iter != end ) {
|
||||
// importer shouldn't give us empty groups of channels!
|
||||
wxASSERT(false);
|
||||
// But correct that and proceed anyway
|
||||
tracks.erase( iter, end );
|
||||
}
|
||||
if (tracks.size() > 0)
|
||||
{
|
||||
// success!
|
||||
|
@ -274,7 +274,10 @@ private:
|
||||
bool mCancelled; //!< True if importing was canceled by user
|
||||
bool mStopped; //!< True if importing was stopped by user
|
||||
wxString mName;
|
||||
std::list<TrackHolders> mChannels; //!< 2-dimentional array of WaveTrack's. First dimention - streams, second - channels of a stream. Length is mNumStreams
|
||||
TrackHolders mChannels; //!< 2-dimensional array of WaveTrack's.
|
||||
//!< First dimension - streams,
|
||||
//!< second - channels of a stream.
|
||||
//!< Length is mNumStreams
|
||||
#ifdef EXPERIMENTAL_OD_FFMPEG
|
||||
bool mUsingOD;
|
||||
#endif
|
||||
@ -688,13 +691,10 @@ ProgressResult FFmpegImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
|
||||
// Copy audio from mChannels to newly created tracks (destroying mChannels elements in process)
|
||||
for (auto &stream : mChannels)
|
||||
{
|
||||
for(auto &channel : stream)
|
||||
{
|
||||
channel->Flush();
|
||||
outTracks.push_back(std::move(channel));
|
||||
}
|
||||
}
|
||||
|
||||
outTracks.swap(mChannels);
|
||||
|
||||
// Save metadata
|
||||
WriteMetadata(tags);
|
||||
|
@ -181,7 +181,7 @@ private:
|
||||
FLAC__uint64 mSamplesDone;
|
||||
bool mStreamInfoDone;
|
||||
ProgressResult mUpdateResult;
|
||||
TrackHolders mChannels;
|
||||
NewChannelGroup mChannels;
|
||||
std::unique_ptr<ODDecodeFlacTask> mDecoderTask;
|
||||
};
|
||||
|
||||
@ -536,10 +536,11 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
return mUpdateResult;
|
||||
}
|
||||
|
||||
for (const auto &channel : mChannels) {
|
||||
for (const auto &channel : mChannels)
|
||||
channel->Flush();
|
||||
}
|
||||
outTracks.swap(mChannels);
|
||||
|
||||
if (!mChannels.empty())
|
||||
outTracks.push_back(std::move(mChannels));
|
||||
|
||||
tags->Clear();
|
||||
size_t cnt = mFile->mComments.GetCount();
|
||||
|
@ -130,7 +130,7 @@ struct GStreamContext
|
||||
GstElement *mConv{}; // Audio converter
|
||||
GstElement *mSink{}; // Application sink
|
||||
bool mUse{}; // True if this stream should be imported
|
||||
TrackHolders mChannels; // Array of WaveTrack pointers, one for each channel
|
||||
NewChannelGroup mChannels; // Array of WaveTrack pointers, one for each channel
|
||||
unsigned mNumChannels{}; // Number of channels
|
||||
gdouble mSampleRate{}; // Sample rate
|
||||
GstString mType; // Audio type
|
||||
@ -1140,18 +1140,6 @@ GStreamerImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
// Grab the streams lock
|
||||
g_mutex_locker locker{ mStreamsLock };
|
||||
|
||||
// Count the total number of tracks collected
|
||||
unsigned outNumTracks = 0;
|
||||
for (guint s = 0; s < mStreams.size(); s++)
|
||||
{
|
||||
GStreamContext *c = mStreams[s].get();
|
||||
if (c)
|
||||
outNumTracks += c->mNumChannels;
|
||||
}
|
||||
|
||||
// Create NEW tracks
|
||||
outTracks.resize(outNumTracks);
|
||||
|
||||
// Copy audio from mChannels to newly created tracks (destroying mChannels in process)
|
||||
int trackindex = 0;
|
||||
for (guint s = 0; s < mStreams.size(); s++)
|
||||
@ -1160,12 +1148,8 @@ GStreamerImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
if (c->mNumChannels)
|
||||
{
|
||||
for (int ch = 0; ch < c->mNumChannels; ch++)
|
||||
{
|
||||
c->mChannels[ch]->Flush();
|
||||
outTracks[trackindex++] = std::move(c->mChannels[ch]);
|
||||
}
|
||||
|
||||
c->mChannels.clear();
|
||||
outTracks.push_back(std::move(c->mChannels));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,8 +223,9 @@ auto LOFImportFileHandle::GetFileUncompressedBytes() -> ByteCount
|
||||
return 0;
|
||||
}
|
||||
|
||||
ProgressResult LOFImportFileHandle::Import(TrackFactory * WXUNUSED(trackFactory), TrackHolders &outTracks,
|
||||
Tags * WXUNUSED(tags))
|
||||
ProgressResult LOFImportFileHandle::Import(
|
||||
TrackFactory * WXUNUSED(trackFactory), TrackHolders &outTracks,
|
||||
Tags * WXUNUSED(tags))
|
||||
{
|
||||
// Unlike other ImportFileHandle subclasses, this one never gives any tracks
|
||||
// back to the caller.
|
||||
|
@ -98,7 +98,7 @@ struct private_data {
|
||||
ArrayOf<unsigned char> inputBuffer{ static_cast<unsigned int>(INPUT_BUFFER_SIZE) };
|
||||
int inputBufferFill; /* amount of data in inputBuffer */
|
||||
TrackFactory *trackFactory;
|
||||
TrackHolders channels;
|
||||
NewChannelGroup channels;
|
||||
ProgressDialog *progress;
|
||||
unsigned numChannels;
|
||||
ProgressResult updateResult;
|
||||
@ -208,8 +208,9 @@ auto MP3ImportFileHandle::GetFileUncompressedBytes() -> ByteCount
|
||||
return 0;
|
||||
}
|
||||
|
||||
ProgressResult MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||
Tags *tags)
|
||||
ProgressResult MP3ImportFileHandle::Import(
|
||||
TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||
Tags *tags)
|
||||
{
|
||||
outTracks.clear();
|
||||
|
||||
@ -252,7 +253,8 @@ ProgressResult MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
||||
for(const auto &channel : privateData.channels) {
|
||||
channel->Flush();
|
||||
}
|
||||
outTracks.swap(privateData.channels);
|
||||
if (!privateData.channels.empty())
|
||||
outTracks.push_back(std::move(privateData.channels));
|
||||
|
||||
/* Read in any metadata */
|
||||
ImportID3(tags);
|
||||
|
@ -155,7 +155,7 @@ private:
|
||||
|
||||
ArrayOf<int> mStreamUsage;
|
||||
wxArrayString mStreamInfo;
|
||||
std::list<TrackHolders> mChannels;
|
||||
std::list<NewChannelGroup> mChannels;
|
||||
|
||||
sampleFormat mFormat;
|
||||
};
|
||||
@ -228,7 +228,8 @@ auto OggImportFileHandle::GetFileUncompressedBytes() -> ByteCount
|
||||
return 0;
|
||||
}
|
||||
|
||||
ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||
ProgressResult OggImportFileHandle::Import(
|
||||
TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||
Tags *tags)
|
||||
{
|
||||
outTracks.clear();
|
||||
@ -374,10 +375,9 @@ ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
||||
|
||||
for (auto &link : mChannels)
|
||||
{
|
||||
for (auto &channel : link) {
|
||||
for (auto &channel : link)
|
||||
channel->Flush();
|
||||
outTracks.push_back(std::move(channel));
|
||||
}
|
||||
outTracks.push_back(std::move(link));
|
||||
}
|
||||
|
||||
//\todo { Extract comments from each stream? }
|
||||
|
@ -364,7 +364,7 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
|
||||
CreateProgress();
|
||||
|
||||
TrackHolders channels(mInfo.channels);
|
||||
NewChannelGroup channels(mInfo.channels);
|
||||
|
||||
auto iter = channels.begin();
|
||||
for (int c = 0; c < mInfo.channels; ++iter, ++c) {
|
||||
@ -529,10 +529,11 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
for(const auto &channel : channels) {
|
||||
for(const auto &channel : channels)
|
||||
channel->Flush();
|
||||
}
|
||||
outTracks.swap(channels);
|
||||
|
||||
if (!channels.empty())
|
||||
outTracks.push_back(std::move(channels));
|
||||
|
||||
const char *str;
|
||||
|
||||
|
@ -157,6 +157,8 @@ public:
|
||||
// The given Tags structure may also be modified.
|
||||
// In case of errors or exceptions, it is not necessary to leave outTracks
|
||||
// or tags unmodified.
|
||||
// If resulting outTracks is not empty,
|
||||
// then each member of it must be a nonempty vector.
|
||||
virtual ProgressResult Import(TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||
Tags *tags) = 0;
|
||||
|
||||
|
@ -336,7 +336,7 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
(sizeof(AudioBuffer) * numchan))) };
|
||||
abl->mNumberBuffers = numchan;
|
||||
|
||||
TrackHolders channels{ numchan };
|
||||
NewChannelGroup channels{ numchan };
|
||||
|
||||
const auto size = sizeof(float) * bufsize;
|
||||
ArraysOf<unsigned char> holders{ numchan, size };
|
||||
@ -395,11 +395,10 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
||||
res = (updateResult == ProgressResult::Success && err == noErr);
|
||||
|
||||
if (res) {
|
||||
for (const auto &channel: channels) {
|
||||
for (auto &channel: channels)
|
||||
channel->Flush();
|
||||
}
|
||||
|
||||
outTracks.swap(channels);
|
||||
if (!channels.empty())
|
||||
outTracks.push_back(std::move(channels));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -107,7 +107,7 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
|
||||
sf_count_t offset = 0;
|
||||
double rate = 44100.0;
|
||||
double percent = 100.0;
|
||||
TrackHolders channels;
|
||||
TrackHolders results;
|
||||
auto updateResult = ProgressResult::Success;
|
||||
|
||||
{
|
||||
@ -200,6 +200,8 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
|
||||
sf_subtype_more_than_16_bits(encoding))
|
||||
format = floatSample;
|
||||
|
||||
results.resize(1);
|
||||
auto &channels = results[0];
|
||||
channels.resize(numChannels);
|
||||
|
||||
auto iter = channels.begin();
|
||||
@ -295,9 +297,11 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
|
||||
if (updateResult == ProgressResult::Failed || updateResult == ProgressResult::Cancelled)
|
||||
throw UserException{};
|
||||
|
||||
for (const auto &channel : channels)
|
||||
channel->Flush();
|
||||
outTracks.swap(channels);
|
||||
if (!results.empty() && !results[0].empty()) {
|
||||
for (const auto &channel : results[0])
|
||||
channel->Flush();
|
||||
outTracks.swap(results);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -21,7 +21,10 @@ class wxWindow;
|
||||
|
||||
#include <vector>
|
||||
|
||||
using TrackHolders = std::vector<std::unique_ptr<WaveTrack>>;
|
||||
// Newly constructed WaveTracks that are not yet owned by a TrackList
|
||||
// are held in unique_ptr not shared_ptr
|
||||
using NewChannelGroup = std::vector< std::unique_ptr<WaveTrack> >;
|
||||
using TrackHolders = std::vector< NewChannelGroup >;
|
||||
|
||||
|
||||
void ImportRaw(wxWindow *parent, const wxString &fileName,
|
||||
|
@ -109,17 +109,17 @@ private:
|
||||
int mStreamIndex;
|
||||
};
|
||||
|
||||
auto ODDecodeFFmpegTask::FromList(const std::list<TrackHolders> &channels) -> Streams
|
||||
auto ODDecodeFFmpegTask::FromList( const TrackHolders &channels ) -> Streams
|
||||
{
|
||||
Streams streams;
|
||||
streams.reserve(channels.size());
|
||||
using namespace std;
|
||||
transform(channels.begin(), channels.end(), back_inserter(streams),
|
||||
[](const TrackHolders &holders) {
|
||||
[](const NewChannelGroup &holders) {
|
||||
Channels channels;
|
||||
channels.reserve(holders.size());
|
||||
transform(holders.begin(), holders.end(), back_inserter(channels),
|
||||
mem_fn(&TrackHolders::value_type::get)
|
||||
mem_fn(&NewChannelGroup::value_type::get)
|
||||
);
|
||||
return channels;
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
using Channels = std::vector < WaveTrack* >;
|
||||
using Streams = std::vector < Channels >;
|
||||
|
||||
static Streams FromList(const std::list<TrackHolders> &channels);
|
||||
static Streams FromList(
|
||||
const std::vector< std::vector< std::unique_ptr<WaveTrack> > > &channels);
|
||||
|
||||
/// Constructs an ODTask
|
||||
ODDecodeFFmpegTask(const ScsPtr &scs, Streams &&channels, const std::shared_ptr<FFmpegContext> &context, int streamIndex);
|
||||
|
Loading…
x
Reference in New Issue
Block a user