mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-03 14:13:11 +02:00
Encapsulate details of setting-up of channel groups in TrackList...
... except that WaveTrack needs to be a friend, just for reloading from disk. Nothing yet is changed in the internal or persistent representation of channel groups.
This commit is contained in:
commit
8fcbbaeea9
@ -7819,6 +7819,7 @@ void MenuCommandHandler::HandleMixAndRender
|
|||||||
WaveTrack::Holder uNewLeft, uNewRight;
|
WaveTrack::Holder uNewLeft, uNewRight;
|
||||||
::MixAndRender(
|
::MixAndRender(
|
||||||
tracks, trackFactory, rate, defaultFormat, 0.0, 0.0, uNewLeft, uNewRight);
|
tracks, trackFactory, rate, defaultFormat, 0.0, 0.0, uNewLeft, uNewRight);
|
||||||
|
tracks->GroupChannels(*uNewLeft, uNewRight ? 2 : 1);
|
||||||
|
|
||||||
if (uNewLeft) {
|
if (uNewLeft) {
|
||||||
// Remove originals, get stats on what tracks were mixed
|
// Remove originals, get stats on what tracks were mixed
|
||||||
@ -8769,22 +8770,20 @@ void MenuCommandHandler::OnNewStereoTrack(const CommandContext &context)
|
|||||||
auto defaultFormat = project.GetDefaultFormat();
|
auto defaultFormat = project.GetDefaultFormat();
|
||||||
auto rate = project.GetRate();
|
auto rate = project.GetRate();
|
||||||
|
|
||||||
auto t = tracks->Add(trackFactory->NewWaveTrack(defaultFormat, rate));
|
|
||||||
t->SetChannel(Track::LeftChannel);
|
|
||||||
project.SelectNone();
|
project.SelectNone();
|
||||||
|
|
||||||
t->SetSelected(true);
|
auto left = tracks->Add(trackFactory->NewWaveTrack(defaultFormat, rate));
|
||||||
t->SetLinked (true);
|
left->SetSelected(true);
|
||||||
|
|
||||||
t = tracks->Add(trackFactory->NewWaveTrack(defaultFormat, rate));
|
auto right = tracks->Add(trackFactory->NewWaveTrack(defaultFormat, rate));
|
||||||
t->SetChannel(Track::RightChannel);
|
right->SetSelected(true);
|
||||||
|
|
||||||
t->SetSelected(true);
|
tracks->GroupChannels(*left, 2);
|
||||||
|
|
||||||
project.PushState(_("Created new stereo audio track"), _("New Track"));
|
project.PushState(_("Created new stereo audio track"), _("New Track"));
|
||||||
|
|
||||||
project.RedrawProject();
|
project.RedrawProject();
|
||||||
trackPanel->EnsureVisible(t);
|
trackPanel->EnsureVisible(left);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuCommandHandler::OnNewLabelTrack(const CommandContext &context)
|
void MenuCommandHandler::OnNewLabelTrack(const CommandContext &context)
|
||||||
|
@ -120,10 +120,7 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
|
|||||||
|
|
||||||
// TODO: more-than-two-channels
|
// TODO: more-than-two-channels
|
||||||
decltype(mixLeft) mixRight{};
|
decltype(mixLeft) mixRight{};
|
||||||
if (mono) {
|
if ( !mono ) {
|
||||||
mixLeft->SetChannel(Track::MonoChannel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mixRight = trackFactory->NewWaveTrack(format, rate);
|
mixRight = trackFactory->NewWaveTrack(format, rate);
|
||||||
if (oneinput) {
|
if (oneinput) {
|
||||||
auto channels = TrackList::Channels(first);
|
auto channels = TrackList::Channels(first);
|
||||||
@ -134,14 +131,10 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
mixRight->SetName(_("Mix"));
|
mixRight->SetName(_("Mix"));
|
||||||
mixLeft->SetChannel(Track::LeftChannel);
|
|
||||||
mixRight->SetChannel(Track::RightChannel);
|
|
||||||
mixRight->SetOffset(mixStartTime);
|
mixRight->SetOffset(mixStartTime);
|
||||||
mixLeft->SetLinked(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto maxBlockLen = mixLeft->GetIdealBlockSize();
|
auto maxBlockLen = mixLeft->GetIdealBlockSize();
|
||||||
|
|
||||||
// If the caller didn't specify a time range, use the whole range in which
|
// If the caller didn't specify a time range, use the whole range in which
|
||||||
|
@ -4168,7 +4168,6 @@ AudacityProject::AddImportedTracks(const wxString &fileName,
|
|||||||
{
|
{
|
||||||
std::vector< std::shared_ptr< Track > > results;
|
std::vector< std::shared_ptr< Track > > results;
|
||||||
|
|
||||||
const auto numTracks = newTracks.size();
|
|
||||||
SelectNone();
|
SelectNone();
|
||||||
|
|
||||||
bool initiallyEmpty = mTracks->empty();
|
bool initiallyEmpty = mTracks->empty();
|
||||||
@ -4177,9 +4176,18 @@ AudacityProject::AddImportedTracks(const wxString &fileName,
|
|||||||
int i = -1;
|
int i = -1;
|
||||||
|
|
||||||
// Must add all tracks first (before using Track::IsLeader)
|
// Must add all tracks first (before using Track::IsLeader)
|
||||||
for (auto &uNewTrack : newTracks) {
|
for (auto &group : newTracks) {
|
||||||
auto newTrack = mTracks->Add(std::move(uNewTrack));
|
if (group.empty()) {
|
||||||
results.push_back(Track::Pointer(newTrack));
|
wxASSERT(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto first = group.begin()->get();
|
||||||
|
auto nChannels = group.size();
|
||||||
|
for (auto &uNewTrack : group) {
|
||||||
|
auto newTrack = mTracks->Add(std::move(uNewTrack));
|
||||||
|
results.push_back(Track::Pointer(newTrack));
|
||||||
|
}
|
||||||
|
mTracks->GroupChannels(*first, nChannels);
|
||||||
}
|
}
|
||||||
newTracks.clear();
|
newTracks.clear();
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ and TimeTrack.
|
|||||||
#include "DirManager.h"
|
#include "DirManager.h"
|
||||||
|
|
||||||
#include "Experimental.h"
|
#include "Experimental.h"
|
||||||
|
#include "InconsistencyException.h"
|
||||||
|
|
||||||
#include "TrackPanel.h" // for TrackInfo
|
#include "TrackPanel.h" // for TrackInfo
|
||||||
|
|
||||||
@ -724,6 +725,58 @@ Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
|
|||||||
template Track *TrackList::Add<Track>(std::shared_ptr<Track> &&);
|
template Track *TrackList::Add<Track>(std::shared_ptr<Track> &&);
|
||||||
template Track *TrackList::Add<WaveTrack>(std::shared_ptr<WaveTrack> &&);
|
template Track *TrackList::Add<WaveTrack>(std::shared_ptr<WaveTrack> &&);
|
||||||
|
|
||||||
|
void TrackList::GroupChannels(
|
||||||
|
Track &track, size_t groupSize, bool resetChannels )
|
||||||
|
{
|
||||||
|
// If group size is more than two, for now only the first two channels
|
||||||
|
// are grouped as stereo, and any others remain mono
|
||||||
|
auto list = track.mList.lock();
|
||||||
|
if ( groupSize > 0 && list.get() == this ) {
|
||||||
|
auto iter = track.mNode.first;
|
||||||
|
auto after = iter;
|
||||||
|
auto end = this->ListOfTracks::end();
|
||||||
|
auto count = groupSize;
|
||||||
|
for ( ; after != end && count--; ++after )
|
||||||
|
;
|
||||||
|
if ( count == 0 ) {
|
||||||
|
auto unlink = [&] ( Track &tr ) {
|
||||||
|
if ( tr.GetLinked() ) {
|
||||||
|
if ( resetChannels ) {
|
||||||
|
auto link = tr.GetLink();
|
||||||
|
if ( link )
|
||||||
|
link->SetChannel( Track::MonoChannel );
|
||||||
|
}
|
||||||
|
tr.SetLinked( false );
|
||||||
|
}
|
||||||
|
if ( resetChannels )
|
||||||
|
tr.SetChannel( Track::MonoChannel );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Disassociate previous tracks -- at most one
|
||||||
|
auto pLeader = this->FindLeader( &track );
|
||||||
|
if ( *pLeader && *pLeader != &track )
|
||||||
|
unlink( **pLeader );
|
||||||
|
|
||||||
|
// First disassociate given and later tracks, then reassociate them
|
||||||
|
for ( auto iter2 = iter; iter2 != after; ++iter2 )
|
||||||
|
unlink( **iter2 );
|
||||||
|
|
||||||
|
if ( groupSize > 1 ) {
|
||||||
|
const auto channel = *iter++;
|
||||||
|
channel->SetLinked( true );
|
||||||
|
channel->SetChannel( Track::LeftChannel );
|
||||||
|
(*iter++)->SetChannel( Track::RightChannel );
|
||||||
|
while (iter != after)
|
||||||
|
(*iter++)->SetChannel( Track::MonoChannel );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// *this does not contain the track or sufficient following channels
|
||||||
|
// or group size is zero
|
||||||
|
throw InconsistencyException{};
|
||||||
|
}
|
||||||
|
|
||||||
auto TrackList::Replace(Track * t, ListOfTracks::value_type &&with) ->
|
auto TrackList::Replace(Track * t, ListOfTracks::value_type &&with) ->
|
||||||
ListOfTracks::value_type
|
ListOfTracks::value_type
|
||||||
{
|
{
|
||||||
|
16
src/Track.h
16
src/Track.h
@ -327,8 +327,11 @@ private:
|
|||||||
|
|
||||||
Track *GetLink() const;
|
Track *GetLink() const;
|
||||||
bool GetLinked () const { return mLinked; }
|
bool GetLinked () const { return mLinked; }
|
||||||
public:
|
|
||||||
|
friend WaveTrack; // WaveTrack needs to call SetLinked when reloading project
|
||||||
void SetLinked (bool l);
|
void SetLinked (bool l);
|
||||||
|
|
||||||
|
void SetChannel(ChannelType c) { mChannel = c; }
|
||||||
private:
|
private:
|
||||||
// No need yet to make this virtual
|
// No need yet to make this virtual
|
||||||
void DoSetLinked(bool l);
|
void DoSetLinked(bool l);
|
||||||
@ -380,7 +383,6 @@ public:
|
|||||||
void Offset(double t) { SetOffset(GetOffset() + t); }
|
void Offset(double t) { SetOffset(GetOffset() + t); }
|
||||||
virtual void SetOffset (double o) { mOffset = o; }
|
virtual void SetOffset (double o) { mOffset = o; }
|
||||||
|
|
||||||
void SetChannel(ChannelType c) { mChannel = c; }
|
|
||||||
virtual void SetPan( float ){ ;}
|
virtual void SetPan( float ){ ;}
|
||||||
virtual void SetPanFromChannelType(){ ;};
|
virtual void SetPanFromChannelType(){ ;};
|
||||||
|
|
||||||
@ -1318,6 +1320,16 @@ public:
|
|||||||
template<typename TrackKind>
|
template<typename TrackKind>
|
||||||
Track *Add(std::shared_ptr<TrackKind> &&t);
|
Track *Add(std::shared_ptr<TrackKind> &&t);
|
||||||
|
|
||||||
|
/** \brief Define a group of channels starting at the given track
|
||||||
|
*
|
||||||
|
* @param track and (groupSize - 1) following tracks must be in this
|
||||||
|
* list. They will be disassociated from any groups they already belong to.
|
||||||
|
* @param groupSize must be at least 1.
|
||||||
|
* @param resetChannels if true, disassociated channels will be marked Mono.
|
||||||
|
*/
|
||||||
|
void GroupChannels(
|
||||||
|
Track &track, size_t groupSize, bool resetChannels = true );
|
||||||
|
|
||||||
/// Replace first track with second track, give back a holder
|
/// Replace first track with second track, give back a holder
|
||||||
/// Give the replacement the same id as the replaced
|
/// Give the replacement the same id as the replaced
|
||||||
ListOfTracks::value_type Replace(Track * t, ListOfTracks::value_type &&with);
|
ListOfTracks::value_type Replace(Track * t, ListOfTracks::value_type &&with);
|
||||||
|
@ -2543,6 +2543,7 @@ void Effect::Preview(bool dryOnly)
|
|||||||
mixRight->SetSelected(true);
|
mixRight->SetSelected(true);
|
||||||
mTracks->Add(std::move(mixRight));
|
mTracks->Add(std::move(mixRight));
|
||||||
}
|
}
|
||||||
|
mTracks->GroupChannels(*mixLeft, mixRight ? 2 : 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (auto src : saveTracks->Any< const WaveTrack >()) {
|
for (auto src : saveTracks->Any< const WaveTrack >()) {
|
||||||
|
@ -157,9 +157,7 @@ bool EffectStereoToMono::ProcessOne(int count)
|
|||||||
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
|
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
|
||||||
outTrack->Flush();
|
outTrack->Flush();
|
||||||
mLeftTrack->Paste(minStart, outTrack.get());
|
mLeftTrack->Paste(minStart, outTrack.get());
|
||||||
mLeftTrack->SetLinked(false);
|
mOutputTracks->GroupChannels( *mLeftTrack, 1 );
|
||||||
mRightTrack->SetLinked(false);
|
|
||||||
mLeftTrack->SetChannel(Track::MonoChannel);
|
|
||||||
mOutputTracks->Remove(mRightTrack);
|
mOutputTracks->Remove(mRightTrack);
|
||||||
|
|
||||||
return bResult;
|
return bResult;
|
||||||
|
@ -49,6 +49,7 @@ and ImportLOF.cpp.
|
|||||||
#include <wx/listimpl.cpp>
|
#include <wx/listimpl.cpp>
|
||||||
#include "../ShuttleGui.h"
|
#include "../ShuttleGui.h"
|
||||||
#include "../Project.h"
|
#include "../Project.h"
|
||||||
|
#include "../WaveTrack.h"
|
||||||
|
|
||||||
#include "ImportPCM.h"
|
#include "ImportPCM.h"
|
||||||
#include "ImportMP3.h"
|
#include "ImportMP3.h"
|
||||||
@ -538,6 +539,15 @@ bool Importer::Import(const wxString &fName,
|
|||||||
return true;
|
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)
|
if (tracks.size() > 0)
|
||||||
{
|
{
|
||||||
// success!
|
// success!
|
||||||
|
@ -274,7 +274,10 @@ private:
|
|||||||
bool mCancelled; //!< True if importing was canceled by user
|
bool mCancelled; //!< True if importing was canceled by user
|
||||||
bool mStopped; //!< True if importing was stopped by user
|
bool mStopped; //!< True if importing was stopped by user
|
||||||
wxString mName;
|
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
|
#ifdef EXPERIMENTAL_OD_FFMPEG
|
||||||
bool mUsingOD;
|
bool mUsingOD;
|
||||||
#endif
|
#endif
|
||||||
@ -520,31 +523,8 @@ ProgressResult FFmpegImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
// There is a possibility that number of channels will change over time, but we do not have WaveTracks for NEW channels. Remember the number of channels and stick to it.
|
// There is a possibility that number of channels will change over time, but we do not have WaveTracks for NEW channels. Remember the number of channels and stick to it.
|
||||||
sc->m_initialchannels = sc->m_stream->codec->channels;
|
sc->m_initialchannels = sc->m_stream->codec->channels;
|
||||||
stream.resize(sc->m_stream->codec->channels);
|
stream.resize(sc->m_stream->codec->channels);
|
||||||
int c = -1;
|
|
||||||
for (auto &channel : stream)
|
for (auto &channel : stream)
|
||||||
{
|
|
||||||
++c;
|
|
||||||
|
|
||||||
channel = trackFactory->NewWaveTrack(sc->m_osamplefmt, sc->m_stream->codec->sample_rate);
|
channel = trackFactory->NewWaveTrack(sc->m_osamplefmt, sc->m_stream->codec->sample_rate);
|
||||||
|
|
||||||
if (sc->m_stream->codec->channels == 2)
|
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
channel->SetChannel(Track::LeftChannel);
|
|
||||||
channel->SetLinked(true);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
channel->SetChannel(Track::RightChannel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
channel->SetChannel(Track::MonoChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles the start_time by creating silence. This may or may not be correct.
|
// Handles the start_time by creating silence. This may or may not be correct.
|
||||||
@ -688,13 +668,10 @@ ProgressResult FFmpegImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
|
|
||||||
// Copy audio from mChannels to newly created tracks (destroying mChannels elements in process)
|
// Copy audio from mChannels to newly created tracks (destroying mChannels elements in process)
|
||||||
for (auto &stream : mChannels)
|
for (auto &stream : mChannels)
|
||||||
{
|
|
||||||
for(auto &channel : stream)
|
for(auto &channel : stream)
|
||||||
{
|
|
||||||
channel->Flush();
|
channel->Flush();
|
||||||
outTracks.push_back(std::move(channel));
|
|
||||||
}
|
outTracks.swap(mChannels);
|
||||||
}
|
|
||||||
|
|
||||||
// Save metadata
|
// Save metadata
|
||||||
WriteMetadata(tags);
|
WriteMetadata(tags);
|
||||||
|
@ -181,7 +181,7 @@ private:
|
|||||||
FLAC__uint64 mSamplesDone;
|
FLAC__uint64 mSamplesDone;
|
||||||
bool mStreamInfoDone;
|
bool mStreamInfoDone;
|
||||||
ProgressResult mUpdateResult;
|
ProgressResult mUpdateResult;
|
||||||
TrackHolders mChannels;
|
NewChannelGroup mChannels;
|
||||||
std::unique_ptr<ODDecodeFlacTask> mDecoderTask;
|
std::unique_ptr<ODDecodeFlacTask> mDecoderTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -455,25 +455,9 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
mChannels.resize(mNumChannels);
|
mChannels.resize(mNumChannels);
|
||||||
|
|
||||||
auto iter = mChannels.begin();
|
auto iter = mChannels.begin();
|
||||||
for (size_t c = 0; c < mNumChannels; ++iter, ++c) {
|
for (size_t c = 0; c < mNumChannels; ++iter, ++c)
|
||||||
*iter = trackFactory->NewWaveTrack(mFormat, mSampleRate);
|
*iter = trackFactory->NewWaveTrack(mFormat, mSampleRate);
|
||||||
|
|
||||||
if (mNumChannels == 2) {
|
|
||||||
switch (c) {
|
|
||||||
case 0:
|
|
||||||
iter->get()->SetChannel(Track::LeftChannel);
|
|
||||||
iter->get()->SetLinked(true);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
iter->get()->SetChannel(Track::RightChannel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iter->get()->SetChannel(Track::MonoChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Start OD
|
//Start OD
|
||||||
bool useOD = false;
|
bool useOD = false;
|
||||||
@ -536,10 +520,11 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
return mUpdateResult;
|
return mUpdateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &channel : mChannels) {
|
for (const auto &channel : mChannels)
|
||||||
channel->Flush();
|
channel->Flush();
|
||||||
}
|
|
||||||
outTracks.swap(mChannels);
|
if (!mChannels.empty())
|
||||||
|
outTracks.push_back(std::move(mChannels));
|
||||||
|
|
||||||
tags->Clear();
|
tags->Clear();
|
||||||
size_t cnt = mFile->mComments.GetCount();
|
size_t cnt = mFile->mComments.GetCount();
|
||||||
|
@ -130,7 +130,7 @@ struct GStreamContext
|
|||||||
GstElement *mConv{}; // Audio converter
|
GstElement *mConv{}; // Audio converter
|
||||||
GstElement *mSink{}; // Application sink
|
GstElement *mSink{}; // Application sink
|
||||||
bool mUse{}; // True if this stream should be imported
|
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
|
unsigned mNumChannels{}; // Number of channels
|
||||||
gdouble mSampleRate{}; // Sample rate
|
gdouble mSampleRate{}; // Sample rate
|
||||||
GstString mType; // Audio type
|
GstString mType; // Audio type
|
||||||
@ -789,14 +789,6 @@ GStreamerImportFileHandle::OnNewSample(GStreamContext *c, GstSample *sample)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set to stereo if there's exactly 2 channels
|
|
||||||
if (c->mNumChannels == 2)
|
|
||||||
{
|
|
||||||
c->mChannels[0]->SetChannel(Track::LeftChannel);
|
|
||||||
c->mChannels[1]->SetChannel(Track::RightChannel);
|
|
||||||
c->mChannels[0]->SetLinked(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the buffer for the sample...no need to release
|
// Get the buffer for the sample...no need to release
|
||||||
@ -1140,18 +1132,6 @@ GStreamerImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
// Grab the streams lock
|
// Grab the streams lock
|
||||||
g_mutex_locker locker{ mStreamsLock };
|
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)
|
// Copy audio from mChannels to newly created tracks (destroying mChannels in process)
|
||||||
int trackindex = 0;
|
int trackindex = 0;
|
||||||
for (guint s = 0; s < mStreams.size(); s++)
|
for (guint s = 0; s < mStreams.size(); s++)
|
||||||
@ -1160,12 +1140,8 @@ GStreamerImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
if (c->mNumChannels)
|
if (c->mNumChannels)
|
||||||
{
|
{
|
||||||
for (int ch = 0; ch < c->mNumChannels; ch++)
|
for (int ch = 0; ch < c->mNumChannels; ch++)
|
||||||
{
|
|
||||||
c->mChannels[ch]->Flush();
|
c->mChannels[ch]->Flush();
|
||||||
outTracks[trackindex++] = std::move(c->mChannels[ch]);
|
outTracks.push_back(std::move(c->mChannels));
|
||||||
}
|
|
||||||
|
|
||||||
c->mChannels.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,8 +223,9 @@ auto LOFImportFileHandle::GetFileUncompressedBytes() -> ByteCount
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressResult LOFImportFileHandle::Import(TrackFactory * WXUNUSED(trackFactory), TrackHolders &outTracks,
|
ProgressResult LOFImportFileHandle::Import(
|
||||||
Tags * WXUNUSED(tags))
|
TrackFactory * WXUNUSED(trackFactory), TrackHolders &outTracks,
|
||||||
|
Tags * WXUNUSED(tags))
|
||||||
{
|
{
|
||||||
// Unlike other ImportFileHandle subclasses, this one never gives any tracks
|
// Unlike other ImportFileHandle subclasses, this one never gives any tracks
|
||||||
// back to the caller.
|
// back to the caller.
|
||||||
|
@ -98,7 +98,7 @@ struct private_data {
|
|||||||
ArrayOf<unsigned char> inputBuffer{ static_cast<unsigned int>(INPUT_BUFFER_SIZE) };
|
ArrayOf<unsigned char> inputBuffer{ static_cast<unsigned int>(INPUT_BUFFER_SIZE) };
|
||||||
int inputBufferFill; /* amount of data in inputBuffer */
|
int inputBufferFill; /* amount of data in inputBuffer */
|
||||||
TrackFactory *trackFactory;
|
TrackFactory *trackFactory;
|
||||||
TrackHolders channels;
|
NewChannelGroup channels;
|
||||||
ProgressDialog *progress;
|
ProgressDialog *progress;
|
||||||
unsigned numChannels;
|
unsigned numChannels;
|
||||||
ProgressResult updateResult;
|
ProgressResult updateResult;
|
||||||
@ -208,8 +208,9 @@ auto MP3ImportFileHandle::GetFileUncompressedBytes() -> ByteCount
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressResult MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHolders &outTracks,
|
ProgressResult MP3ImportFileHandle::Import(
|
||||||
Tags *tags)
|
TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||||
|
Tags *tags)
|
||||||
{
|
{
|
||||||
outTracks.clear();
|
outTracks.clear();
|
||||||
|
|
||||||
@ -252,7 +253,8 @@ ProgressResult MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||||||
for(const auto &channel : privateData.channels) {
|
for(const auto &channel : privateData.channels) {
|
||||||
channel->Flush();
|
channel->Flush();
|
||||||
}
|
}
|
||||||
outTracks.swap(privateData.channels);
|
if (!privateData.channels.empty())
|
||||||
|
outTracks.push_back(std::move(privateData.channels));
|
||||||
|
|
||||||
/* Read in any metadata */
|
/* Read in any metadata */
|
||||||
ImportID3(tags);
|
ImportID3(tags);
|
||||||
@ -501,17 +503,9 @@ enum mad_flow output_cb(void *_data,
|
|||||||
|
|
||||||
auto format = QualityPrefs::SampleFormatChoice();
|
auto format = QualityPrefs::SampleFormatChoice();
|
||||||
|
|
||||||
for(auto &channel: data->channels) {
|
for(auto &channel: data->channels)
|
||||||
channel = data->trackFactory->NewWaveTrack(format, samplerate);
|
channel = data->trackFactory->NewWaveTrack(format, samplerate);
|
||||||
channel->SetChannel(Track::MonoChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* special case: 2 channels is understood to be stereo */
|
|
||||||
if(channels == 2) {
|
|
||||||
data->channels.begin()->get()->SetChannel(Track::LeftChannel);
|
|
||||||
data->channels.rbegin()->get()->SetChannel(Track::RightChannel);
|
|
||||||
data->channels.begin()->get()->SetLinked(true);
|
|
||||||
}
|
|
||||||
data->numChannels = channels;
|
data->numChannels = channels;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -155,7 +155,7 @@ private:
|
|||||||
|
|
||||||
ArrayOf<int> mStreamUsage;
|
ArrayOf<int> mStreamUsage;
|
||||||
wxArrayString mStreamInfo;
|
wxArrayString mStreamInfo;
|
||||||
std::list<TrackHolders> mChannels;
|
std::list<NewChannelGroup> mChannels;
|
||||||
|
|
||||||
sampleFormat mFormat;
|
sampleFormat mFormat;
|
||||||
};
|
};
|
||||||
@ -228,7 +228,8 @@ auto OggImportFileHandle::GetFileUncompressedBytes() -> ByteCount
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHolders &outTracks,
|
ProgressResult OggImportFileHandle::Import(
|
||||||
|
TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||||
Tags *tags)
|
Tags *tags)
|
||||||
{
|
{
|
||||||
outTracks.clear();
|
outTracks.clear();
|
||||||
@ -258,27 +259,8 @@ ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||||||
|
|
||||||
link.resize(vi->channels);
|
link.resize(vi->channels);
|
||||||
|
|
||||||
int c = -1;
|
for (auto &channel : link)
|
||||||
for (auto &channel : link) {
|
|
||||||
++c;
|
|
||||||
|
|
||||||
channel = trackFactory->NewWaveTrack(mFormat, vi->rate);
|
channel = trackFactory->NewWaveTrack(mFormat, vi->rate);
|
||||||
|
|
||||||
if (vi->channels == 2) {
|
|
||||||
switch (c) {
|
|
||||||
case 0:
|
|
||||||
channel->SetChannel(Track::LeftChannel);
|
|
||||||
channel->SetLinked(true);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
channel->SetChannel(Track::RightChannel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
channel->SetChannel(Track::MonoChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The number of bytes to get from the codec in each run */
|
/* The number of bytes to get from the codec in each run */
|
||||||
@ -374,10 +356,9 @@ ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||||||
|
|
||||||
for (auto &link : mChannels)
|
for (auto &link : mChannels)
|
||||||
{
|
{
|
||||||
for (auto &channel : link) {
|
for (auto &channel : link)
|
||||||
channel->Flush();
|
channel->Flush();
|
||||||
outTracks.push_back(std::move(channel));
|
outTracks.push_back(std::move(link));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//\todo { Extract comments from each stream? }
|
//\todo { Extract comments from each stream? }
|
||||||
|
@ -364,29 +364,12 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
|
|
||||||
CreateProgress();
|
CreateProgress();
|
||||||
|
|
||||||
TrackHolders channels(mInfo.channels);
|
NewChannelGroup channels(mInfo.channels);
|
||||||
|
|
||||||
auto iter = channels.begin();
|
auto iter = channels.begin();
|
||||||
for (int c = 0; c < mInfo.channels; ++iter, ++c) {
|
for (int c = 0; c < mInfo.channels; ++iter, ++c)
|
||||||
*iter = trackFactory->NewWaveTrack(mFormat, mInfo.samplerate);
|
*iter = trackFactory->NewWaveTrack(mFormat, mInfo.samplerate);
|
||||||
|
|
||||||
if (mInfo.channels > 1)
|
|
||||||
switch (c) {
|
|
||||||
case 0:
|
|
||||||
iter->get()->SetChannel(Track::LeftChannel);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
iter->get()->SetChannel(Track::RightChannel);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
iter->get()->SetChannel(Track::MonoChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mInfo.channels == 2) {
|
|
||||||
channels.begin()->get()->SetLinked(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto fileTotalFrames =
|
auto fileTotalFrames =
|
||||||
(sampleCount)mInfo.frames; // convert from sf_count_t
|
(sampleCount)mInfo.frames; // convert from sf_count_t
|
||||||
auto maxBlockSize = channels.begin()->get()->GetMaxBlockSize();
|
auto maxBlockSize = channels.begin()->get()->GetMaxBlockSize();
|
||||||
@ -529,10 +512,11 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
return updateResult;
|
return updateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const auto &channel : channels) {
|
for(const auto &channel : channels)
|
||||||
channel->Flush();
|
channel->Flush();
|
||||||
}
|
|
||||||
outTracks.swap(channels);
|
if (!channels.empty())
|
||||||
|
outTracks.push_back(std::move(channels));
|
||||||
|
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|
||||||
|
@ -157,6 +157,8 @@ public:
|
|||||||
// The given Tags structure may also be modified.
|
// The given Tags structure may also be modified.
|
||||||
// In case of errors or exceptions, it is not necessary to leave outTracks
|
// In case of errors or exceptions, it is not necessary to leave outTracks
|
||||||
// or tags unmodified.
|
// 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,
|
virtual ProgressResult Import(TrackFactory *trackFactory, TrackHolders &outTracks,
|
||||||
Tags *tags) = 0;
|
Tags *tags) = 0;
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
(sizeof(AudioBuffer) * numchan))) };
|
(sizeof(AudioBuffer) * numchan))) };
|
||||||
abl->mNumberBuffers = numchan;
|
abl->mNumberBuffers = numchan;
|
||||||
|
|
||||||
TrackHolders channels{ numchan };
|
NewChannelGroup channels{ numchan };
|
||||||
|
|
||||||
const auto size = sizeof(float) * bufsize;
|
const auto size = sizeof(float) * bufsize;
|
||||||
ArraysOf<unsigned char> holders{ numchan, size };
|
ArraysOf<unsigned char> holders{ numchan, size };
|
||||||
@ -352,16 +352,6 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
|
|
||||||
channel = trackFactory->NewWaveTrack( format );
|
channel = trackFactory->NewWaveTrack( format );
|
||||||
channel->SetRate( desc.mSampleRate );
|
channel->SetRate( desc.mSampleRate );
|
||||||
|
|
||||||
if (numchan == 2) {
|
|
||||||
if (c == 0) {
|
|
||||||
channel->SetChannel(Track::LeftChannel);
|
|
||||||
channel->SetLinked(true);
|
|
||||||
}
|
|
||||||
else if (c == 1) {
|
|
||||||
channel->SetChannel(Track::RightChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -395,11 +385,10 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
|||||||
res = (updateResult == ProgressResult::Success && err == noErr);
|
res = (updateResult == ProgressResult::Success && err == noErr);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
for (const auto &channel: channels) {
|
for (auto &channel: channels)
|
||||||
channel->Flush();
|
channel->Flush();
|
||||||
}
|
if (!channels.empty())
|
||||||
|
outTracks.push_back(std::move(channels));
|
||||||
outTracks.swap(channels);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -107,7 +107,7 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
|
|||||||
sf_count_t offset = 0;
|
sf_count_t offset = 0;
|
||||||
double rate = 44100.0;
|
double rate = 44100.0;
|
||||||
double percent = 100.0;
|
double percent = 100.0;
|
||||||
TrackHolders channels;
|
TrackHolders results;
|
||||||
auto updateResult = ProgressResult::Success;
|
auto updateResult = ProgressResult::Success;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -200,31 +200,15 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
|
|||||||
sf_subtype_more_than_16_bits(encoding))
|
sf_subtype_more_than_16_bits(encoding))
|
||||||
format = floatSample;
|
format = floatSample;
|
||||||
|
|
||||||
|
results.resize(1);
|
||||||
|
auto &channels = results[0];
|
||||||
channels.resize(numChannels);
|
channels.resize(numChannels);
|
||||||
|
|
||||||
auto iter = channels.begin();
|
auto iter = channels.begin();
|
||||||
for (decltype(numChannels) c = 0; c < numChannels; ++iter, ++c) {
|
for (decltype(numChannels) c = 0; c < numChannels; ++iter, ++c)
|
||||||
const auto channel =
|
*iter = trackFactory->NewWaveTrack(format, rate);
|
||||||
(*iter = trackFactory->NewWaveTrack(format, rate)).get();
|
|
||||||
|
|
||||||
if (numChannels > 1)
|
|
||||||
switch (c) {
|
|
||||||
case 0:
|
|
||||||
channel->SetChannel(Track::LeftChannel);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
channel->SetChannel(Track::RightChannel);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
channel->SetChannel(Track::MonoChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto firstChannel = channels.begin()->get();
|
const auto firstChannel = channels.begin()->get();
|
||||||
if (numChannels == 2) {
|
|
||||||
firstChannel->SetLinked(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto maxBlockSize = firstChannel->GetMaxBlockSize();
|
auto maxBlockSize = firstChannel->GetMaxBlockSize();
|
||||||
|
|
||||||
SampleBuffer srcbuffer(maxBlockSize * numChannels, format);
|
SampleBuffer srcbuffer(maxBlockSize * numChannels, format);
|
||||||
@ -295,9 +279,11 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
|
|||||||
if (updateResult == ProgressResult::Failed || updateResult == ProgressResult::Cancelled)
|
if (updateResult == ProgressResult::Failed || updateResult == ProgressResult::Cancelled)
|
||||||
throw UserException{};
|
throw UserException{};
|
||||||
|
|
||||||
for (const auto &channel : channels)
|
if (!results.empty() && !results[0].empty()) {
|
||||||
channel->Flush();
|
for (const auto &channel : results[0])
|
||||||
outTracks.swap(channels);
|
channel->Flush();
|
||||||
|
outTracks.swap(results);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -21,7 +21,10 @@ class wxWindow;
|
|||||||
|
|
||||||
#include <vector>
|
#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,
|
void ImportRaw(wxWindow *parent, const wxString &fileName,
|
||||||
|
@ -109,17 +109,17 @@ private:
|
|||||||
int mStreamIndex;
|
int mStreamIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ODDecodeFFmpegTask::FromList(const std::list<TrackHolders> &channels) -> Streams
|
auto ODDecodeFFmpegTask::FromList( const TrackHolders &channels ) -> Streams
|
||||||
{
|
{
|
||||||
Streams streams;
|
Streams streams;
|
||||||
streams.reserve(channels.size());
|
streams.reserve(channels.size());
|
||||||
using namespace std;
|
using namespace std;
|
||||||
transform(channels.begin(), channels.end(), back_inserter(streams),
|
transform(channels.begin(), channels.end(), back_inserter(streams),
|
||||||
[](const TrackHolders &holders) {
|
[](const NewChannelGroup &holders) {
|
||||||
Channels channels;
|
Channels channels;
|
||||||
channels.reserve(holders.size());
|
channels.reserve(holders.size());
|
||||||
transform(holders.begin(), holders.end(), back_inserter(channels),
|
transform(holders.begin(), holders.end(), back_inserter(channels),
|
||||||
mem_fn(&TrackHolders::value_type::get)
|
mem_fn(&NewChannelGroup::value_type::get)
|
||||||
);
|
);
|
||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ public:
|
|||||||
using Channels = std::vector < WaveTrack* >;
|
using Channels = std::vector < WaveTrack* >;
|
||||||
using Streams = std::vector < Channels >;
|
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
|
/// Constructs an ODTask
|
||||||
ODDecodeFFmpegTask(const ScsPtr &scs, Streams &&channels, const std::shared_ptr<FFmpegContext> &context, int streamIndex);
|
ODDecodeFFmpegTask(const ScsPtr &scs, Streams &&channels, const std::shared_ptr<FFmpegContext> &context, int streamIndex);
|
||||||
|
@ -1164,10 +1164,13 @@ bool ControlToolBar::DoRecord(AudacityProject &project,
|
|||||||
|
|
||||||
wxString baseTrackName = recordingNameCustom? defaultRecordingTrackName : defaultTrackName;
|
wxString baseTrackName = recordingNameCustom? defaultRecordingTrackName : defaultTrackName;
|
||||||
|
|
||||||
|
Track *first {};
|
||||||
for (int c = 0; c < recordingChannels; c++) {
|
for (int c = 0; c < recordingChannels; c++) {
|
||||||
std::shared_ptr<WaveTrack> newTrack{
|
std::shared_ptr<WaveTrack> newTrack{
|
||||||
p->GetTrackFactory()->NewWaveTrack().release()
|
p->GetTrackFactory()->NewWaveTrack().release()
|
||||||
};
|
};
|
||||||
|
if (!first)
|
||||||
|
first = newTrack.get();
|
||||||
|
|
||||||
// Quantize bounds to the rate of the new track.
|
// Quantize bounds to the rate of the new track.
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
@ -1215,26 +1218,14 @@ bool ControlToolBar::DoRecord(AudacityProject &project,
|
|||||||
newTrack->SetMinimized(true);
|
newTrack->SetMinimized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recordingChannels == 2) {
|
|
||||||
if (c == 0) {
|
|
||||||
newTrack->SetChannel(Track::LeftChannel);
|
|
||||||
newTrack->SetLinked(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newTrack->SetChannel(Track::RightChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newTrack->SetChannel( Track::MonoChannel );
|
|
||||||
}
|
|
||||||
|
|
||||||
p->GetTracks()->RegisterPendingNewTrack( newTrack );
|
p->GetTracks()->RegisterPendingNewTrack( newTrack );
|
||||||
transportTracks.captureTracks.push_back(newTrack);
|
transportTracks.captureTracks.push_back(newTrack);
|
||||||
// Bug 1548. New track needs the focus.
|
// Bug 1548. New track needs the focus.
|
||||||
p->GetTrackPanel()->SetFocusedTrack( newTrack.get() );
|
p->GetTrackPanel()->SetFocusedTrack( newTrack.get() );
|
||||||
}
|
}
|
||||||
|
p->GetTracks()->GroupChannels(*first, recordingChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Automated Input Level Adjustment Initialization
|
//Automated Input Level Adjustment Initialization
|
||||||
#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
|
#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
|
||||||
gAudioIO->AILAInitialize();
|
gAudioIO->AILAInitialize();
|
||||||
|
@ -802,6 +802,7 @@ void WaveTrackMenuTable::OnSpectrogramSettings(wxCommandEvent &)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void WaveTrackMenuTable::OnChannelChange(wxCommandEvent & event)
|
void WaveTrackMenuTable::OnChannelChange(wxCommandEvent & event)
|
||||||
{
|
{
|
||||||
int id = event.GetId();
|
int id = event.GetId();
|
||||||
@ -834,6 +835,7 @@ void WaveTrackMenuTable::OnChannelChange(wxCommandEvent & event)
|
|||||||
_("Channel"));
|
_("Channel"));
|
||||||
mpData->result = RefreshCode::RefreshAll;
|
mpData->result = RefreshCode::RefreshAll;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Merge two tracks into one stereo track ??
|
/// Merge two tracks into one stereo track ??
|
||||||
void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &)
|
void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &)
|
||||||
@ -847,46 +849,39 @@ void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &)
|
|||||||
auto partner = static_cast< WaveTrack * >
|
auto partner = static_cast< WaveTrack * >
|
||||||
( *tracks->Find( pTrack ).advance( 1 ) );
|
( *tracks->Find( pTrack ).advance( 1 ) );
|
||||||
|
|
||||||
pTrack->SetLinked(true);
|
tracks->GroupChannels( *pTrack, 2 );
|
||||||
|
|
||||||
if (partner) {
|
// Set partner's parameters to match target.
|
||||||
// Set partner's parameters to match target.
|
partner->Merge(*pTrack);
|
||||||
partner->Merge(*pTrack);
|
|
||||||
|
|
||||||
pTrack->SetPan( 0.0f );
|
pTrack->SetPan( 0.0f );
|
||||||
pTrack->SetChannel(Track::LeftChannel);
|
partner->SetPan( 0.0f );
|
||||||
partner->SetPan( 0.0f );
|
|
||||||
partner->SetChannel(Track::RightChannel);
|
|
||||||
|
|
||||||
// Set NEW track heights and minimized state
|
// Set NEW track heights and minimized state
|
||||||
bool bBothMinimizedp = ((pTrack->GetMinimized()) && (partner->GetMinimized()));
|
bool bBothMinimizedp = ((pTrack->GetMinimized()) && (partner->GetMinimized()));
|
||||||
pTrack->SetMinimized(false);
|
pTrack->SetMinimized(false);
|
||||||
partner->SetMinimized(false);
|
partner->SetMinimized(false);
|
||||||
int AverageHeight = (pTrack->GetHeight() + partner->GetHeight()) / 2;
|
int AverageHeight = (pTrack->GetHeight() + partner->GetHeight()) / 2;
|
||||||
pTrack->SetHeight(AverageHeight);
|
pTrack->SetHeight(AverageHeight);
|
||||||
partner->SetHeight(AverageHeight);
|
partner->SetHeight(AverageHeight);
|
||||||
pTrack->SetMinimized(bBothMinimizedp);
|
pTrack->SetMinimized(bBothMinimizedp);
|
||||||
partner->SetMinimized(bBothMinimizedp);
|
partner->SetMinimized(bBothMinimizedp);
|
||||||
|
|
||||||
//On Demand - join the queues together.
|
//On Demand - join the queues together.
|
||||||
if (ODManager::IsInstanceCreated())
|
if (ODManager::IsInstanceCreated())
|
||||||
if (!ODManager::Instance()->MakeWaveTrackDependent(partner, pTrack))
|
if (!ODManager::Instance()->MakeWaveTrackDependent(partner, pTrack))
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
//TODO: in the future, we will have to check the return value of MakeWaveTrackDependent -
|
//TODO: in the future, we will have to check the return value of MakeWaveTrackDependent -
|
||||||
//if the tracks cannot merge, it returns false, and in that case we should not allow a merging.
|
//if the tracks cannot merge, it returns false, and in that case we should not allow a merging.
|
||||||
//for example it returns false when there are two different types of ODTasks on each track's queue.
|
//for example it returns false when there are two different types of ODTasks on each track's queue.
|
||||||
//we will need to display this to the user.
|
//we will need to display this to the user.
|
||||||
}
|
}
|
||||||
|
|
||||||
AudacityProject *const project = ::GetActiveProject();
|
/* i18n-hint: The string names a track */
|
||||||
/* i18n-hint: The string names a track */
|
project->PushState(wxString::Format(_("Made '%s' a stereo track"),
|
||||||
project->PushState(wxString::Format(_("Made '%s' a stereo track"),
|
pTrack->GetName()),
|
||||||
pTrack->GetName()),
|
_("Make Stereo"));
|
||||||
_("Make Stereo"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pTrack->SetLinked(false);
|
|
||||||
|
|
||||||
mpData->result = RefreshCode::RefreshAll;
|
mpData->result = RefreshCode::RefreshAll;
|
||||||
}
|
}
|
||||||
@ -899,7 +894,6 @@ void WaveTrackMenuTable::SplitStereo(bool stereo)
|
|||||||
AudacityProject *const project = ::GetActiveProject();
|
AudacityProject *const project = ::GetActiveProject();
|
||||||
auto channels = TrackList::Channels( pTrack );
|
auto channels = TrackList::Channels( pTrack );
|
||||||
|
|
||||||
|
|
||||||
int totalHeight = 0;
|
int totalHeight = 0;
|
||||||
int nChannels = 0;
|
int nChannels = 0;
|
||||||
for (auto channel : channels) {
|
for (auto channel : channels) {
|
||||||
@ -907,7 +901,6 @@ void WaveTrackMenuTable::SplitStereo(bool stereo)
|
|||||||
channel->SetName(pTrack->GetName());
|
channel->SetName(pTrack->GetName());
|
||||||
if (stereo)
|
if (stereo)
|
||||||
channel->SetPanFromChannelType();
|
channel->SetPanFromChannelType();
|
||||||
channel->SetChannel(Track::MonoChannel);
|
|
||||||
|
|
||||||
//On Demand - have each channel add its own.
|
//On Demand - have each channel add its own.
|
||||||
if (ODManager::IsInstanceCreated())
|
if (ODManager::IsInstanceCreated())
|
||||||
@ -919,7 +912,7 @@ void WaveTrackMenuTable::SplitStereo(bool stereo)
|
|||||||
++nChannels;
|
++nChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
pTrack->SetLinked(false);
|
project->GetTracks()->GroupChannels( *pTrack, 1 );
|
||||||
int averageHeight = totalHeight / nChannels;
|
int averageHeight = totalHeight / nChannels;
|
||||||
|
|
||||||
for (auto channel : channels)
|
for (auto channel : channels)
|
||||||
@ -947,12 +940,9 @@ void WaveTrackMenuTable::OnSwapChannels(wxCommandEvent &)
|
|||||||
|
|
||||||
SplitStereo(false);
|
SplitStereo(false);
|
||||||
|
|
||||||
first->SetChannel(Track::RightChannel);
|
|
||||||
partner->SetChannel(Track::LeftChannel);
|
|
||||||
|
|
||||||
TrackList *const tracks = project->GetTracks();
|
TrackList *const tracks = project->GetTracks();
|
||||||
(tracks->MoveUp(partner));
|
tracks->MoveUp( partner );
|
||||||
partner->SetLinked(true);
|
tracks->GroupChannels( *partner, 2 );
|
||||||
|
|
||||||
MixerBoard* pMixerBoard = project->GetMixerBoard();
|
MixerBoard* pMixerBoard = project->GetMixerBoard();
|
||||||
if (pMixerBoard)
|
if (pMixerBoard)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user