pianobooster/src/TrackList.h

214 lines
5.8 KiB
C++

/*********************************************************************************/
/*!
@file TrackList.h
@brief xxxx.
@author L. J. Barman
Copyright (c) 2008-2013, L. J. Barman, all rights reserved
This file is part of the PianoBooster application
PianoBooster is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PianoBooster is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PianoBooster. If not, see <http://www.gnu.org/licenses/>.
*/
/*********************************************************************************/
#ifndef __TRACK_LIST_H__
#define __TRACK_LIST_H__
#include <QString>
#include <QList>
#include <QListWidgetItem>
#include <QObject>
#include "MidiEvent.h"
#include "Chord.h"
#define CONVENTION_LEFT_HAND_CHANNEL (3-1)
#define CONVENTION_RIGHT_HAND_CHANNEL (4-1)
class CSong;
class CSettings;
class AnalyseItem
{
public:
AnalyseItem() {}
AnalyseItem(int numberOfTracks)
{
m_noteCount = 0;
for(int i = 0; i < numberOfTracks; i++) {
QSharedPointer<int> notePtr (new int[MAX_MIDI_NOTES]);
memset(notePtr.data(), 0, sizeof(int) * MAX_MIDI_NOTES );
m_noteFrequencyByTrack.append( notePtr) ;
m_noteCountByTrack.append(0);
}
}
void addNoteEvent(CMidiEvent event){
m_noteCount++;
int trackNo = event.track();
m_noteCountByTrack[trackNo]++;
int *noteFrequency = m_noteFrequencyByTrack[trackNo].data();
int note = event.note();
// count each note so we can guess the key signature
if (note >= 0 && note< MAX_MIDI_NOTES) {
(*(noteFrequency + note))++;
}
// If we have a note and no patch then default to grand piano patch
if (m_firstPatch == -1 && event.channel() != MIDI_DRUM_CHANNEL) {
m_firstPatch = GM_PIANO_PATCH;
}
}
int noteCount() const {return m_noteCount;}
int active() {return m_noteCount >0;}
void addPatch(int patch){
if (m_firstPatch == -1) {
m_firstPatch = patch;
}
}
int firstPatch() {return m_firstPatch;}
int trackCount() {
int acitveTracks = 0;
for (int track = 0; track < m_noteCountByTrack.size(); track++) {
if (m_noteCountByTrack[track] > 0) {
acitveTracks++;
}
}
return acitveTracks;
}
int rightHandTrack() {
if (trackCount() <= 1) {
return -1;
}
double highestAveragePitch = 0.0;
int rightHAndTrack = 1;
for (int track = 0; track < m_noteCountByTrack.size(); track++) {
if (m_noteCountByTrack[track] > 0) {
double averagePitch = averageNotePitch(track);
if (averagePitch > highestAveragePitch ) {
highestAveragePitch = averagePitch;
rightHAndTrack = track;
}
}
}
return rightHAndTrack;
}
double averageNotePitch(int trackNo) const {
int totalNoteCount = 0;
double sumOffAllPitches = 0.0;
int *noteFrequency = m_noteFrequencyByTrack[trackNo].data();
for (int note = 0; note < MAX_MIDI_NOTES; note++) {
int frequency = *(noteFrequency + note);
totalNoteCount += frequency;
sumOffAllPitches += frequency * note;
}
return sumOffAllPitches / totalNoteCount;
}
private:
int m_noteCount = 0;
int m_firstPatch = -1;
QVector<QSharedPointer<int>> m_noteFrequencyByTrack;
QVector<int> m_noteCountByTrack;
};
class CTrackListItem
{
public:
CTrackListItem(int midiChannel) :
m_midiChannel(midiChannel)
{
}
int midiChannel() const {return m_midiChannel;}
private:
int m_midiChannel;
};
class CTrackList : public QObject
{
Q_OBJECT
public:
CTrackList()
{
m_song = 0;
m_settings = 0;
reset(0);
}
void init(CSong* songObj, CSettings* settings);
void refresh();
void reset(int numberOfTracks);
// Find an unused channel
int findFreeChannel(int startChannel);
void currentRowChanged(int currentRow);
void examineMidiEvent(CMidiEvent event);
bool pianoPartConvetionTest();
bool findLeftAndRightPianoParts();
int guessKeySignature(int chanA, int chanB);
// The programme name now starts at 1 with 0 = "(none)"
static QString getProgramName(int program);
QStringList getAllChannelProgramNames(bool raw=false);
int getActiveItemIndex();
int getActiveHandIndex(whichPart_t whichPart);
// set the midi channels to use for the left and right hand piano parts
void setActiveHandsIndex(int leftIndex, int rightIndex);
int getHandTrackIndex(whichPart_t whichPart);
void changeListWidgetItemView(int index, QListWidgetItem* listWidgetItem);
double averageNotePitch(int chan) {
int totalNoteCount = 0;
double sumOffAllPitches = 0.0;
for (int note = 0; note < MAX_MIDI_NOTES; note++) {
int frequency = m_noteFrequency[chan][note];
totalNoteCount += frequency;
sumOffAllPitches += frequency * note;
}
return sumOffAllPitches / totalNoteCount;
}
private:
QString getChannelProgramName(int chan);
CSong* m_song;
CSettings* m_settings;
QList<CTrackListItem> m_partsList;
QVector<AnalyseItem> m_midiChannels;
int m_noteFrequency[MAX_MIDI_CHANNELS][MAX_MIDI_NOTES];
};
#endif //__TRACK_LIST_H__