mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-13 23:27:43 +02:00
Iterations over channels where more general messages may be needed...
... but otherwise the logic generalizes without a problem. All these places have the comment: // TODO: more-than-two-channels-message
This commit is contained in:
commit
70f7b0f6ef
116
src/Menus.cpp
116
src/Menus.cpp
@ -3856,13 +3856,14 @@ double MenuCommandHandler::OnClipMove
|
|||||||
|
|
||||||
auto t0 = selectedRegion.t0();
|
auto t0 = selectedRegion.t0();
|
||||||
|
|
||||||
state.capturedClip = wt->GetClipAtTime( t0 );
|
// Find the first channel that has a clip at time t0
|
||||||
if (state.capturedClip == nullptr && track->GetLinked() && track->GetLink()) {
|
for (auto channel : TrackList::Channels(wt) ) {
|
||||||
// the clips in the right channel may be different from the left
|
if( nullptr != (state.capturedClip = channel->GetClipAtTime( t0 )) ) {
|
||||||
track = track->GetLink();
|
wt = channel;
|
||||||
wt = static_cast<WaveTrack*>(track);
|
break;
|
||||||
state.capturedClip = wt->GetClipAtTime(t0);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (state.capturedClip == nullptr)
|
if (state.capturedClip == nullptr)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
@ -6906,25 +6907,23 @@ int MenuCommandHandler::FindClips
|
|||||||
std::vector<FoundClip> results;
|
std::vector<FoundClip> results;
|
||||||
|
|
||||||
int nTracksSearched = 0;
|
int nTracksSearched = 0;
|
||||||
int trackNum = 1;
|
auto leaders = tracks->Leaders();
|
||||||
for (auto track : tracks->Leaders()) {
|
auto range = leaders.Filter<const WaveTrack>();
|
||||||
if (track->GetKind() == Track::Wave && (!anyWaveTracksSelected || track->GetSelected())) {
|
if (anyWaveTracksSelected)
|
||||||
auto waveTrack = static_cast<const WaveTrack*>(track);
|
range = range + &Track::GetSelected;
|
||||||
bool stereoAndDiff = waveTrack->GetLinked() && !ChannelsHaveSameClipBoundaries(waveTrack);
|
for (auto waveTrack : range) {
|
||||||
|
bool stereoAndDiff = ChannelsHaveDifferentClipBoundaries(waveTrack);
|
||||||
|
|
||||||
auto result = next ? FindNextClip(project, waveTrack, t0, t1) :
|
auto range = stereoAndDiff
|
||||||
FindPrevClip(project, waveTrack, t0, t1);
|
? TrackList::Channels( waveTrack )
|
||||||
|
: TrackList::SingletonRange( waveTrack );
|
||||||
|
|
||||||
|
for ( auto wt : range ) {
|
||||||
|
auto result = next ? FindNextClip(project, wt, t0, t1) :
|
||||||
|
FindPrevClip(project, wt, t0, t1);
|
||||||
if (result.found) {
|
if (result.found) {
|
||||||
result.trackNum = trackNum;
|
result.trackNum =
|
||||||
result.channel = stereoAndDiff;
|
1 + std::distance( leaders.begin(), leaders.find( waveTrack ) );
|
||||||
results.push_back(result);
|
|
||||||
}
|
|
||||||
if (stereoAndDiff) {
|
|
||||||
auto waveTrack2 = static_cast<const WaveTrack*>(track->GetLink());
|
|
||||||
auto result = next ? FindNextClip(project, waveTrack2, t0, t1) :
|
|
||||||
FindPrevClip(project, waveTrack2, t0, t1);
|
|
||||||
if (result.found) {
|
|
||||||
result.trackNum = trackNum;
|
|
||||||
result.channel = stereoAndDiff;
|
result.channel = stereoAndDiff;
|
||||||
results.push_back(result);
|
results.push_back(result);
|
||||||
}
|
}
|
||||||
@ -6933,9 +6932,6 @@ int MenuCommandHandler::FindClips
|
|||||||
nTracksSearched++;
|
nTracksSearched++;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackNum++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (results.size() > 0) {
|
if (results.size() > 0) {
|
||||||
// if any clips were found,
|
// if any clips were found,
|
||||||
@ -6974,14 +6970,13 @@ int MenuCommandHandler::FindClips
|
|||||||
return nTracksSearched; // can be used for screen reader messages if required
|
return nTracksSearched; // can be used for screen reader messages if required
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether the two channels of a stereo track have the same clips
|
namespace {
|
||||||
bool MenuCommandHandler::ChannelsHaveSameClipBoundaries(const WaveTrack* wt)
|
bool TwoChannelsHaveSameBoundaries
|
||||||
{
|
( const WaveTrack *first, const WaveTrack *second )
|
||||||
|
{
|
||||||
bool sameClips = false;
|
bool sameClips = false;
|
||||||
|
auto& left = first->GetClips();
|
||||||
if (wt->GetLinked() && wt->GetLink()) {
|
auto& right = second->GetClips();
|
||||||
auto& left = wt->GetClips();
|
|
||||||
auto& right = static_cast<const WaveTrack*>(wt->GetLink())->GetClips();
|
|
||||||
if (left.size() == right.size()) {
|
if (left.size() == right.size()) {
|
||||||
sameClips = true;
|
sameClips = true;
|
||||||
for (unsigned int i = 0; i < left.size(); i++) {
|
for (unsigned int i = 0; i < left.size(); i++) {
|
||||||
@ -6992,9 +6987,24 @@ bool MenuCommandHandler::ChannelsHaveSameClipBoundaries(const WaveTrack* wt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return sameClips;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MenuCommandHandler::ChannelsHaveDifferentClipBoundaries(
|
||||||
|
const WaveTrack* wt)
|
||||||
|
{
|
||||||
|
// This is quadratic in the number of channels
|
||||||
|
auto channels = TrackList::Channels(wt);
|
||||||
|
while (!channels.empty()) {
|
||||||
|
auto channel = *channels.first++;
|
||||||
|
for (auto other : channels) {
|
||||||
|
if (!TwoChannelsHaveSameBoundaries(channel, other))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sameClips;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuCommandHandler::OnSelectPrevClip(const CommandContext &context)
|
void MenuCommandHandler::OnSelectPrevClip(const CommandContext &context)
|
||||||
@ -8120,25 +8130,23 @@ int MenuCommandHandler::FindClipBoundaries
|
|||||||
std::vector<FoundClipBoundary> results;
|
std::vector<FoundClipBoundary> results;
|
||||||
|
|
||||||
int nTracksSearched = 0;
|
int nTracksSearched = 0;
|
||||||
int trackNum = 1;
|
auto leaders = tracks->Leaders();
|
||||||
for (auto track : tracks->Leaders()) {
|
auto range = leaders.Filter<const WaveTrack>();
|
||||||
if (track->GetKind() == Track::Wave && (!anyWaveTracksSelected || track->GetSelected())) {
|
if (anyWaveTracksSelected)
|
||||||
auto waveTrack = static_cast<const WaveTrack*>(track);
|
range = range + &Track::GetSelected;
|
||||||
bool stereoAndDiff = waveTrack->GetLinked() && !ChannelsHaveSameClipBoundaries(waveTrack);
|
for (auto waveTrack : range) {
|
||||||
|
bool stereoAndDiff = ChannelsHaveDifferentClipBoundaries(waveTrack);
|
||||||
|
|
||||||
auto result = next ? FindNextClipBoundary(waveTrack, time) :
|
auto range = stereoAndDiff
|
||||||
FindPrevClipBoundary(waveTrack, time);
|
? TrackList::Channels( waveTrack )
|
||||||
|
: TrackList::SingletonRange(waveTrack);
|
||||||
|
|
||||||
|
for (auto wt : range) {
|
||||||
|
auto result = next ? FindNextClipBoundary(wt, time) :
|
||||||
|
FindPrevClipBoundary(wt, time);
|
||||||
if (result.nFound > 0) {
|
if (result.nFound > 0) {
|
||||||
result.trackNum = trackNum;
|
result.trackNum =
|
||||||
result.channel = stereoAndDiff;
|
1 + std::distance( leaders.begin(), leaders.find( waveTrack ) );
|
||||||
results.push_back(result);
|
|
||||||
}
|
|
||||||
if (stereoAndDiff) {
|
|
||||||
waveTrack = static_cast<const WaveTrack*>(track->GetLink());
|
|
||||||
result = next ? FindNextClipBoundary(waveTrack, time) :
|
|
||||||
FindPrevClipBoundary(waveTrack, time);
|
|
||||||
if (result.nFound > 0) {
|
|
||||||
result.trackNum = trackNum;
|
|
||||||
result.channel = stereoAndDiff;
|
result.channel = stereoAndDiff;
|
||||||
results.push_back(result);
|
results.push_back(result);
|
||||||
}
|
}
|
||||||
@ -8147,9 +8155,6 @@ int MenuCommandHandler::FindClipBoundaries
|
|||||||
nTracksSearched++;
|
nTracksSearched++;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackNum++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (results.size() > 0) {
|
if (results.size() > 0) {
|
||||||
// If any clip boundaries were found
|
// If any clip boundaries were found
|
||||||
@ -8215,7 +8220,8 @@ wxString MenuCommandHandler::FoundTrack::ComposeTrackName() const
|
|||||||
: name;
|
: name;
|
||||||
auto longName = shortName;
|
auto longName = shortName;
|
||||||
if (channel) {
|
if (channel) {
|
||||||
if ( waveTrack->GetLinked() )
|
// TODO: more-than-two-channels-message
|
||||||
|
if ( waveTrack->IsLeader() )
|
||||||
/* i18n-hint: given the name of a track, specify its left channel */
|
/* i18n-hint: given the name of a track, specify its left channel */
|
||||||
longName = wxString::Format(_("%s left"), shortName);
|
longName = wxString::Format(_("%s left"), shortName);
|
||||||
else
|
else
|
||||||
|
@ -357,7 +357,7 @@ FoundClip FindPrevClip
|
|||||||
int FindClips
|
int FindClips
|
||||||
(AudacityProject &project,
|
(AudacityProject &project,
|
||||||
double t0, double t1, bool next, std::vector<FoundClip>& results);
|
double t0, double t1, bool next, std::vector<FoundClip>& results);
|
||||||
bool ChannelsHaveSameClipBoundaries(const WaveTrack* wt);
|
bool ChannelsHaveDifferentClipBoundaries(const WaveTrack* wt);
|
||||||
void OnSelectPrevClip(const CommandContext &context );
|
void OnSelectPrevClip(const CommandContext &context );
|
||||||
void OnSelectNextClip(const CommandContext &context );
|
void OnSelectNextClip(const CommandContext &context );
|
||||||
void OnSelectClip(AudacityProject &project, bool next);
|
void OnSelectClip(AudacityProject &project, bool next);
|
||||||
|
@ -1078,23 +1078,17 @@ void TrackPanel::RefreshTrack(Track *trk, bool refreshbacking)
|
|||||||
if (!trk)
|
if (!trk)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Track *link = trk->GetLink();
|
trk = *GetTracks()->FindLeader(trk);
|
||||||
|
auto height =
|
||||||
if (link && !trk->GetLinked()) {
|
TrackList::Channels(trk).sum( &Track::GetHeight )
|
||||||
trk = link;
|
- kTopInset - kShadowThickness;
|
||||||
link = trk->GetLink();
|
|
||||||
}
|
|
||||||
|
|
||||||
// subtract insets and shadows from the rectangle, but not border
|
// subtract insets and shadows from the rectangle, but not border
|
||||||
// This matters because some separators do paint over the border
|
// This matters because some separators do paint over the border
|
||||||
wxRect rect(kLeftInset,
|
wxRect rect(kLeftInset,
|
||||||
-mViewInfo->vpos + trk->GetY() + kTopInset,
|
-mViewInfo->vpos + trk->GetY() + kTopInset,
|
||||||
GetRect().GetWidth() - kLeftInset - kRightInset - kShadowThickness,
|
GetRect().GetWidth() - kLeftInset - kRightInset - kShadowThickness,
|
||||||
trk->GetHeight() - kTopInset - kShadowThickness);
|
height);
|
||||||
|
|
||||||
if (link) {
|
|
||||||
rect.height += link->GetHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( refreshbacking )
|
if( refreshbacking )
|
||||||
{
|
{
|
||||||
@ -1184,41 +1178,24 @@ void TrackPanel::DrawEverythingElse(TrackPanelDrawingContext &context,
|
|||||||
trackRect.y = t->GetY() - mViewInfo->vpos;
|
trackRect.y = t->GetY() - mViewInfo->vpos;
|
||||||
trackRect.height = t->GetHeight();
|
trackRect.height = t->GetHeight();
|
||||||
|
|
||||||
// If this track is linked to the next one, display a common
|
auto leaderTrack = *GetTracks()->FindLeader( t );
|
||||||
// border for both, otherwise draw a normal border
|
|
||||||
wxRect rect = trackRect;
|
|
||||||
bool skipBorder = false;
|
|
||||||
Track *l = t->GetLink();
|
|
||||||
|
|
||||||
if (l && t->GetLinked()) {
|
|
||||||
rect.height += l->GetHeight();
|
|
||||||
}
|
|
||||||
else if (l && trackRect.y >= 0) {
|
|
||||||
skipBorder = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the previous track is linked to this one but isn't on the screen
|
// If the previous track is linked to this one but isn't on the screen
|
||||||
// (and thus would have been skipped) we need to draw that track's border
|
// (and thus would have been skipped) we need to draw that track's border
|
||||||
// instead.
|
// instead.
|
||||||
const Track *borderTrack = t;
|
bool drawBorder = (t == leaderTrack || trackRect.y < 0);
|
||||||
wxRect borderRect = rect;
|
|
||||||
|
|
||||||
if (l && !t->GetLinked() && trackRect.y < 0)
|
if (drawBorder) {
|
||||||
{
|
wxRect teamRect = trackRect;
|
||||||
borderTrack = l;
|
teamRect.y = leaderTrack->GetY() - mViewInfo->vpos;
|
||||||
|
// danger with pending tracks?
|
||||||
|
teamRect.height =
|
||||||
|
TrackList::Channels(leaderTrack)
|
||||||
|
.sum( &Track::GetHeight );
|
||||||
|
|
||||||
borderRect = trackRect;
|
|
||||||
borderRect.y = l->GetY() - mViewInfo->vpos;
|
|
||||||
borderRect.height = l->GetHeight();
|
|
||||||
|
|
||||||
borderRect.height += t->GetHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skipBorder) {
|
|
||||||
if (mAx->IsFocused(t)) {
|
if (mAx->IsFocused(t)) {
|
||||||
focusRect = borderRect;
|
focusRect = teamRect;
|
||||||
}
|
}
|
||||||
DrawOutside(context, borderTrack, borderRect);
|
DrawOutside(context, leaderTrack, teamRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Believe it or not, we can speed up redrawing if we don't
|
// Believe it or not, we can speed up redrawing if we don't
|
||||||
@ -1675,7 +1652,9 @@ void TrackInfo::Status1DrawFunction
|
|||||||
/// stereo and what sample rate it's using.
|
/// stereo and what sample rate it's using.
|
||||||
auto rate = wt ? wt->GetRate() : 44100.0;
|
auto rate = wt ? wt->GetRate() : 44100.0;
|
||||||
wxString s;
|
wxString s;
|
||||||
if (!wt || (wt->GetLinked()))
|
if (!pTrack || TrackList::Channels(pTrack).size() > 1)
|
||||||
|
// TODO: more-than-two-channels-message
|
||||||
|
// more appropriate strings
|
||||||
s = _("Stereo, %dHz");
|
s = _("Stereo, %dHz");
|
||||||
else {
|
else {
|
||||||
if (wt->GetChannel() == Track::MonoChannel)
|
if (wt->GetChannel() == Track::MonoChannel)
|
||||||
@ -1714,6 +1693,15 @@ void TrackPanel::DrawOutside
|
|||||||
wxRect rect = rec;
|
wxRect rect = rec;
|
||||||
DrawOutsideOfTrack(context, t, rect);
|
DrawOutsideOfTrack(context, t, rect);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto channels = TrackList::Channels(t);
|
||||||
|
// omit last (perhaps, only) channel
|
||||||
|
--channels.second;
|
||||||
|
for (auto channel : channels)
|
||||||
|
// draw the sash below this channel
|
||||||
|
DrawSash(channel, dc, rect);
|
||||||
|
}
|
||||||
|
|
||||||
// Now exclude left, right, and top insets
|
// Now exclude left, right, and top insets
|
||||||
rect.x += kLeftInset;
|
rect.x += kLeftInset;
|
||||||
rect.y += kTopInset;
|
rect.y += kTopInset;
|
||||||
@ -1733,7 +1721,16 @@ void TrackPanel::DrawOutside
|
|||||||
// TrackArtist::DrawSyncLockTiles(dc, tileFill);
|
// TrackArtist::DrawSyncLockTiles(dc, tileFill);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
DrawBordersAroundTrack(t, dc, rect, labelw, vrul);
|
DrawBordersAroundTrack(dc, rect, vrul);
|
||||||
|
{
|
||||||
|
auto channels = TrackList::Channels(t);
|
||||||
|
// omit last (perhaps, only) channel
|
||||||
|
--channels.second;
|
||||||
|
for (auto channel : channels)
|
||||||
|
// draw the sash below this channel
|
||||||
|
DrawBordersAroundSash(channel, dc, rect, labelw);
|
||||||
|
}
|
||||||
|
|
||||||
DrawShadow(t, dc, rect);
|
DrawShadow(t, dc, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1777,16 +1774,17 @@ void TrackPanel::DrawOutsideOfTrack
|
|||||||
side.x += side.width - kRightInset;
|
side.x += side.width - kRightInset;
|
||||||
side.width = kRightInset;
|
side.width = kRightInset;
|
||||||
dc->DrawRectangle(side);
|
dc->DrawRectangle(side);
|
||||||
|
}
|
||||||
|
|
||||||
// Area between tracks of stereo group
|
void TrackPanel::DrawSash(const Track * t, wxDC * dc, const wxRect & rect)
|
||||||
if (t->GetLinked()) {
|
{
|
||||||
// Paint the channel separator over (what would be) the shadow of the top
|
// Area between channels of a group
|
||||||
// channel, and the top inset of the bottom channel
|
// Paint the channel separator over (what would be) the shadow of this
|
||||||
side = rect;
|
// channel, and the top inset of the following channel
|
||||||
side.y += t->GetHeight() - kShadowThickness;
|
wxRect side = rect;
|
||||||
|
side.y = t->GetY() - mViewInfo->vpos + t->GetHeight() - kShadowThickness;
|
||||||
side.height = kTopInset + kShadowThickness;
|
side.height = kTopInset + kShadowThickness;
|
||||||
dc->DrawRectangle(side);
|
dc->DrawRectangle(side);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackPanel::SetBackgroundCell
|
void TrackPanel::SetBackgroundCell
|
||||||
@ -1979,8 +1977,8 @@ void TrackPanel::VerticalScroll( float fracPosition){
|
|||||||
// Given rectangle excludes the insets left, right, and top
|
// Given rectangle excludes the insets left, right, and top
|
||||||
// Draw a rectangular border and also a vertical separator of track controls
|
// Draw a rectangular border and also a vertical separator of track controls
|
||||||
// from the rest (ruler and proper track area)
|
// from the rest (ruler and proper track area)
|
||||||
void TrackPanel::DrawBordersAroundTrack(const Track * t, wxDC * dc,
|
void TrackPanel::DrawBordersAroundTrack(wxDC * dc,
|
||||||
const wxRect & rect, const int labelw,
|
const wxRect & rect,
|
||||||
const int vrul)
|
const int vrul)
|
||||||
{
|
{
|
||||||
// Border around track and label area
|
// Border around track and label area
|
||||||
@ -1991,21 +1989,21 @@ void TrackPanel::DrawBordersAroundTrack(const Track * t, wxDC * dc,
|
|||||||
rect.width - kShadowThickness,
|
rect.width - kShadowThickness,
|
||||||
rect.height - kShadowThickness);
|
rect.height - kShadowThickness);
|
||||||
|
|
||||||
|
|
||||||
// between vruler and TrackInfo
|
// between vruler and TrackInfo
|
||||||
AColor::Line(*dc, vrul, rect.y, vrul, rect.y + rect.height - 1);
|
AColor::Line(*dc, vrul, rect.y, vrul, rect.y + rect.height - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// The lines at bottom of 1st track and top of second track of stereo group
|
void TrackPanel::DrawBordersAroundSash(const Track * t, wxDC * dc,
|
||||||
// Possibly replace with DrawRectangle to add left border.
|
const wxRect & rect, const int labelw)
|
||||||
if (t->GetLinked()) {
|
{
|
||||||
// The given rect has had the top inset subtracted
|
int h1 = t->GetY() - mViewInfo->vpos + t->GetHeight();
|
||||||
int h1 = rect.y + t->GetHeight() - kTopInset;
|
// h1 is the top coordinate of the following channel's rectangle
|
||||||
// h1 is the top coordinate of the second tracks' rectangle
|
|
||||||
// Draw (part of) the bottom border of the top channel and top border of the bottom
|
// Draw (part of) the bottom border of the top channel and top border of the bottom
|
||||||
// At left it extends between the vertical rulers too
|
// At left it extends between the vertical rulers too
|
||||||
// These lines stroke over what is otherwise "border" of each channel
|
// These lines stroke over what is otherwise "border" of each channel
|
||||||
AColor::Line(*dc, labelw, h1 - kBottomMargin, rect.x + rect.width - 1, h1 - kBottomMargin);
|
AColor::Line(*dc, labelw, h1 - kBottomMargin, rect.x + rect.width - 1, h1 - kBottomMargin);
|
||||||
AColor::Line(*dc, labelw, h1 + kTopInset, rect.x + rect.width - 1, h1 + kTopInset);
|
AColor::Line(*dc, labelw, h1 + kTopInset, rect.x + rect.width - 1, h1 + kTopInset);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given rectangle has insets subtracted left, right, and top
|
// Given rectangle has insets subtracted left, right, and top
|
||||||
|
@ -373,16 +373,20 @@ protected:
|
|||||||
void DrawEverythingElse(TrackPanelDrawingContext &context,
|
void DrawEverythingElse(TrackPanelDrawingContext &context,
|
||||||
const wxRegion & region,
|
const wxRegion & region,
|
||||||
const wxRect & clip);
|
const wxRect & clip);
|
||||||
void DrawOutside
|
void DrawOutside(
|
||||||
(TrackPanelDrawingContext &context,
|
TrackPanelDrawingContext &context,
|
||||||
const Track *t, const wxRect & rec);
|
const Track *leaderTrack, const wxRect & teamRect);
|
||||||
|
|
||||||
void HighlightFocusedTrack (wxDC* dc, const wxRect &rect);
|
void HighlightFocusedTrack (wxDC* dc, const wxRect &rect);
|
||||||
void DrawShadow (const Track *t, wxDC* dc, const wxRect & rect);
|
void DrawShadow (const Track *t, wxDC* dc, const wxRect & rect);
|
||||||
void DrawBordersAroundTrack(const Track *t, wxDC* dc, const wxRect & rect, const int labelw, const int vrul);
|
void DrawBordersAroundTrack(wxDC* dc, const wxRect & rect,
|
||||||
void DrawOutsideOfTrack
|
const int vrul);
|
||||||
(TrackPanelDrawingContext &context,
|
void DrawBordersAroundSash (const Track *t, wxDC* dc, const wxRect & rect,
|
||||||
|
const int labelw);
|
||||||
|
void DrawOutsideOfTrack (
|
||||||
|
TrackPanelDrawingContext &context,
|
||||||
const Track *t, const wxRect & rect);
|
const Track *t, const wxRect & rect);
|
||||||
|
void DrawSash (const Track *t, wxDC* dc, const wxRect & rect);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Set the object that performs catch-all event handling when the pointer
|
// Set the object that performs catch-all event handling when the pointer
|
||||||
|
@ -219,10 +219,6 @@ bool EffectNormalize::Process()
|
|||||||
//Iterate over each track
|
//Iterate over each track
|
||||||
this->CopyInputTracks(); // Set up mOutputTracks.
|
this->CopyInputTracks(); // Set up mOutputTracks.
|
||||||
bool bGoodResult = true;
|
bool bGoodResult = true;
|
||||||
SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks.get());
|
|
||||||
WaveTrack *track = (WaveTrack *) iter.First();
|
|
||||||
WaveTrack *prevTrack;
|
|
||||||
prevTrack = track;
|
|
||||||
double progress = 0;
|
double progress = 0;
|
||||||
wxString topMsg;
|
wxString topMsg;
|
||||||
if(mDC && mGain)
|
if(mDC && mGain)
|
||||||
@ -234,8 +230,10 @@ bool EffectNormalize::Process()
|
|||||||
else if(!mDC && !mGain)
|
else if(!mDC && !mGain)
|
||||||
topMsg = _("Not doing anything...\n"); // shouldn't get here
|
topMsg = _("Not doing anything...\n"); // shouldn't get here
|
||||||
|
|
||||||
while (track) {
|
for ( auto track : mOutputTracks->Selected< WaveTrack >()
|
||||||
|
+ ( mStereoInd ? &Track::Any : &Track::IsLeader ) ) {
|
||||||
//Get start and end times from track
|
//Get start and end times from track
|
||||||
|
// PRL: No accounting for multiple channels?
|
||||||
double trackStart = track->GetStartTime();
|
double trackStart = track->GetStartTime();
|
||||||
double trackEnd = track->GetEndTime();
|
double trackEnd = track->GetEndTime();
|
||||||
|
|
||||||
@ -244,28 +242,65 @@ bool EffectNormalize::Process()
|
|||||||
mCurT0 = mT0 < trackStart? trackStart: mT0;
|
mCurT0 = mT0 < trackStart? trackStart: mT0;
|
||||||
mCurT1 = mT1 > trackEnd? trackEnd: mT1;
|
mCurT1 = mT1 > trackEnd? trackEnd: mT1;
|
||||||
|
|
||||||
|
auto range = mStereoInd
|
||||||
|
? TrackList::SingletonRange(track)
|
||||||
|
: TrackList::Channels(track);
|
||||||
|
|
||||||
// Process only if the right marker is to the right of the left marker
|
// Process only if the right marker is to the right of the left marker
|
||||||
if (mCurT1 > mCurT0) {
|
if (mCurT1 > mCurT0) {
|
||||||
wxString msg;
|
wxString trackName = track->GetName();
|
||||||
auto trackName = track->GetName();
|
|
||||||
|
|
||||||
if(!track->GetLinked() || mStereoInd)
|
float extent;
|
||||||
msg =
|
#ifdef EXPERIMENTAL_R128_NORM
|
||||||
topMsg + wxString::Format( _("Analyzing: %s"), trackName );
|
if (mUseLoudness)
|
||||||
|
// Loudness: use sum of both tracks.
|
||||||
|
// As a result, stereo tracks appear about 3 LUFS louder,
|
||||||
|
// as specified.
|
||||||
|
extent = 0;
|
||||||
else
|
else
|
||||||
msg =
|
#endif
|
||||||
topMsg + wxString::Format( _("Analyzing first track of stereo pair: %s"), trackName );
|
// Will compute a maximum
|
||||||
float offset, extent;
|
extent = std::numeric_limits<float>::lowest();
|
||||||
bGoodResult = AnalyseTrack(track, msg, progress, offset, extent);
|
std::vector<float> offsets;
|
||||||
if (!bGoodResult )
|
|
||||||
break;
|
wxString msg;
|
||||||
if(!track->GetLinked() || mStereoInd) {
|
if (range.size() == 1)
|
||||||
// mono or 'stereo tracks independently'
|
// mono or 'stereo tracks independently'
|
||||||
if( (extent > 0) && mGain )
|
msg = topMsg +
|
||||||
{
|
wxString::Format( _("Analyzing: %s"), trackName );
|
||||||
|
else
|
||||||
|
msg = topMsg +
|
||||||
|
// TODO: more-than-two-channels-message
|
||||||
|
wxString::Format( _("Analyzing first track of stereo pair: %s"), trackName);
|
||||||
|
|
||||||
|
// Analysis loop over channels collects offsets and extent
|
||||||
|
for (auto channel : range) {
|
||||||
|
float offset, extent2;
|
||||||
|
bGoodResult =
|
||||||
|
AnalyseTrack( channel, msg, progress, offset, extent2 );
|
||||||
|
if ( ! bGoodResult )
|
||||||
|
goto break2;
|
||||||
|
#ifdef EXPERIMENTAL_R128_NORM
|
||||||
|
if (mUseLoudness)
|
||||||
|
extent += extent2;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
extent = std::max( extent, extent2 );
|
||||||
|
offsets.push_back(offset);
|
||||||
|
// TODO: more-than-two-channels-message
|
||||||
|
msg = topMsg +
|
||||||
|
wxString::Format( _("Analyzing second track of stereo pair: %s"), trackName );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the multiplier using extent
|
||||||
|
if( (extent > 0) && mGain ) {
|
||||||
mMult = ratio / extent;
|
mMult = ratio / extent;
|
||||||
#ifdef EXPERIMENTAL_R128_NORM
|
#ifdef EXPERIMENTAL_R128_NORM
|
||||||
if(mUseLoudness) {
|
if(mUseLoudness) {
|
||||||
|
// PRL: See commit 9cbb67a for the origin of the next line,
|
||||||
|
// which has no effect because mMult is again overwritten. What
|
||||||
|
// was the intent?
|
||||||
|
|
||||||
// LUFS is defined as -0.691 dB + 10*log10(sum(channels))
|
// LUFS is defined as -0.691 dB + 10*log10(sum(channels))
|
||||||
mMult /= 0.8529037031;
|
mMult /= 0.8529037031;
|
||||||
// LUFS are related to square values so the multiplier must be the root.
|
// LUFS are related to square values so the multiplier must be the root.
|
||||||
@ -276,88 +311,36 @@ bool EffectNormalize::Process()
|
|||||||
else
|
else
|
||||||
mMult = 1.0;
|
mMult = 1.0;
|
||||||
|
|
||||||
msg =
|
if (range.size() == 1) {
|
||||||
topMsg + wxString::Format( _("Processing: %s"), trackName );
|
if (TrackList::Channels(track).size() == 1)
|
||||||
|
// really mono
|
||||||
if(track->GetLinked() || prevTrack->GetLinked()) // only get here if there is a linked track but we are processing independently
|
msg = topMsg +
|
||||||
msg =
|
wxString::Format( _("Processing: %s"), trackName );
|
||||||
topMsg + wxString::Format( _("Processing stereo channels independently: %s"), trackName );
|
else
|
||||||
|
//'stereo tracks independently'
|
||||||
if (!ProcessOne(track, msg, progress, offset))
|
// TODO: more-than-two-channels-message
|
||||||
{
|
msg = topMsg +
|
||||||
bGoodResult = false;
|
wxString::Format( _("Processing stereo channels independently: %s"), trackName);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// we have a linked stereo track
|
|
||||||
// so we need to find it's min, max and offset
|
|
||||||
// as they are needed to calc the multiplier for both tracks
|
|
||||||
|
|
||||||
track = (WaveTrack *) iter.Next(); // get the next one
|
|
||||||
msg =
|
|
||||||
topMsg + wxString::Format( _("Analyzing second track of stereo pair: %s"), trackName );
|
|
||||||
|
|
||||||
float offset2, extent2;
|
|
||||||
bGoodResult = AnalyseTrack(track, msg, progress, offset2, extent2);
|
|
||||||
if ( !bGoodResult )
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_R128_NORM
|
|
||||||
if (mUseLoudness) {
|
|
||||||
// Loudness: use sum of both tracks.
|
|
||||||
// As a result, stereo tracks appear about 3 LUFS louder, as specified.
|
|
||||||
extent = extent + extent2;
|
|
||||||
// LUFS is defined as -0.691 dB + 10*log10(sum(channels))
|
|
||||||
extent *= 0.8529037031;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Peak: use maximum of both tracks.
|
|
||||||
extent = fmax(extent, extent2);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Peak: use maximum of both tracks.
|
|
||||||
extent = fmax(extent, extent2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( (extent > 0) && mGain )
|
|
||||||
{
|
|
||||||
mMult = ratio / extent; // we need to use this for both linked tracks
|
|
||||||
#ifdef EXPERIMENTAL_R128_NORM
|
|
||||||
if(mUseLoudness) {
|
|
||||||
// LUFS are related to square values so the multiplier must be the root.
|
|
||||||
mMult = sqrt(mMult);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mMult = 1.0;
|
msg = topMsg +
|
||||||
|
// TODO: more-than-two-channels-message
|
||||||
|
wxString::Format( _("Processing first track of stereo pair: %s"), trackName);
|
||||||
|
|
||||||
track = (WaveTrack *) iter.Prev(); // go back to the first linked one
|
// Use multiplier in the second, processing loop over channels
|
||||||
msg =
|
auto pOffset = offsets.begin();
|
||||||
topMsg + wxString::Format( _("Processing first track of stereo pair: %s"), trackName );
|
for (auto channel : range) {
|
||||||
|
if (false ==
|
||||||
if (!ProcessOne(track, msg, progress, offset))
|
(bGoodResult = ProcessOne(channel, msg, progress, *pOffset++)) )
|
||||||
{
|
goto break2;
|
||||||
bGoodResult = false;
|
// TODO: more-than-two-channels-message
|
||||||
break;
|
msg = topMsg +
|
||||||
}
|
wxString::Format( _("Processing second track of stereo pair: %s"), trackName);
|
||||||
track = (WaveTrack *) iter.Next(); // go to the second linked one
|
|
||||||
msg =
|
|
||||||
topMsg + wxString::Format( _("Processing second track of stereo pair: %s"), trackName );
|
|
||||||
|
|
||||||
if (!ProcessOne(track, msg, progress, offset2))
|
|
||||||
{
|
|
||||||
bGoodResult = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Iterate to the next track
|
break2:
|
||||||
prevTrack = track;
|
|
||||||
track = (WaveTrack *) iter.Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->ReplaceProcessedTracks(bGoodResult);
|
this->ReplaceProcessedTracks(bGoodResult);
|
||||||
return bGoodResult;
|
return bGoodResult;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user