Just Intonation  Version 1.3.0 (18)
Explore scale-independent dynamically adapting tuning in just intonation
scale.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright 2016-2017 Karolin Stange, Christoph Wick, and Haye Hinrichsen
3  *
4  * This file is part of JustIntonation.
5  *
6  * JustIntonation is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * JustIntonation is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with JustIntonation. If not, see http://www.gnu.org/licenses/.
18  *****************************************************************************/
19 
20 //=============================================================================
21 // Scale
22 //=============================================================================
23 
24 #include "scale.h"
25 
26 #include <QDebug>
27 #include <QThread>
28 
29 #include "instrumentfilehandler.h"
30 #include "voice.h"
31 
32 #define STATUS if (Voice::mVerbosity >= 4) qDebug() << "Scale:"
33 #define MESSAGE if (Voice::mVerbosity >= 3) qDebug() << "Scale:"
34 #define WARNING if (Voice::mVerbosity >= 2) qWarning()<<"Scale: WARNING:"
35 #define ERROR if (Voice::mVerbosity >= 1) qCritical() << "Scale: ERROR:"
36 
37 //-----------------------------------------------------------------------------
38 // Access function
39 //-----------------------------------------------------------------------------
43 
44 Scale::Scale() : mWaves(N) , mCancellationRequested(false)
45 {}
46 
47 
48 //-----------------------------------------------------------------------------
49 // Access function
50 //-----------------------------------------------------------------------------
56 
57 Wave &Scale::getWave(int &key)
58 { return mWaves[key & 0x7F]; }
59 
60 
61 //-----------------------------------------------------------------------------
62 // Compute artificial sounds
63 //-----------------------------------------------------------------------------
69 
70 void Scale::generateArtificialSound (Voice* voice, int samplerate)
71 {
72  mCancellationRequested = false;
73  const double A4 = 440;
74  double progress=0;
75  for (int n=21; n<=108; ++n)
76  {
77  progress += 1.0/88;
78  if (voice) voice->setProgress(QVariant(progress));
79  if (QThread::currentThread()->isInterruptionRequested()) return;
80  double frequ = A4*pow(2,(n-69.0)/12.0);
81  mWaves[n].computeTriangularWave (frequ,samplerate,(n-20)/88.0);
82  if (mCancellationRequested) break;
83  }
84 }
85 
86 
87 //-----------------------------------------------------------------------------
88 // Insert new wave data (called from importer)
89 //-----------------------------------------------------------------------------
102 
103 bool Scale::insert (const int key,
104  const QVector<qint32> &L,
105  const QVector<qint32> &R,
106  const bool release,
107  const double amplification)
108 {
109  if (key<0 or key>127)
110  {
111  qDebug() << "Scale::insert: key" << key << "out of range";
112  return false;
113  }
114  if (L.size()==0 or L.size()!=R.size())
115  {
116  qDebug() << "Scale::insert of key" << key <<": Waveform sizes"
117  << L.size() << R.size() << "inconsistent";
118  return false;
119  }
120  if (mWaves.size() != N) // this should never happen
121  {
122  qDebug() << "Scale::insert: mWaveForm size =" << mWaves.size() << "invalid";
123  return false;
124  }
125  if (L.size() > 1<<20)
126  {
127  qDebug() << "Scale::insert: ERROR: mWaveForm exceeds maximal size 2^20";
128  return false;
129  }
130  return mWaves[key].insert(L,R,release,amplification);
131 }
132 
133 //-----------------------------------------------------------------------------
134 // Write scale data to device
135 //-----------------------------------------------------------------------------
144 
145 bool Scale::write(QIODevice &iodevice, Voice* voice)
146 {
148  // Count nonzero entries
149  int cnt=0;
150  for (Wave &waveform : mWaves) if (waveform.waveFormExists()) cnt++;
151  InstrumentFileHandler::write(iodevice,cnt);
152 
153  // Write file
154  double progress=0;
155  for (Wave &waveform : mWaves)
156  {
157  if (cnt) progress += 1.0/cnt; else progress=1;
158  if (voice) voice->setProgress(QVariant(progress));
159  if (not waveform.write(iodevice)) return false;
160  if (mCancellationRequested) break;
161  }
162  return true;
163 }
164 
165 
166 //-----------------------------------------------------------------------------
167 // Read scale data from device
168 //-----------------------------------------------------------------------------
175 
176 bool Scale::read (QIODevice &iodevice, Voice* voice)
177 {
178  mCancellationRequested = false;
179  int tag=0, cnt=0;
180  InstrumentFileHandler::read (iodevice,tag);
181  InstrumentFileHandler::read (iodevice,cnt);
182  if (tag != ctag)
183  {
184  qWarning() << "Scale::read: invalid tag.";
185  return false;
186  }
187 
188  double progress = 0;
189  for (Wave &waveform : mWaves)
190  {
191  if (not waveform.read(iodevice)) return false;
192  if (waveform.waveFormExists() and cnt>0) progress += 1.0/cnt;
193  if (voice) emit voice->setProgress(QVariant(progress));
194  if (mCancellationRequested) break;
195  }
196  return not mCancellationRequested;
197 }
198 
199 
200 //-----------------------------------------------------------------------------
201 // Print information about this scale
202 //-----------------------------------------------------------------------------
206 
208 {
209  qDebug() << " Scale with" << mWaves.size() << "waveforms.";
210  for (int n=0; n<128; ++n) mWaves[n].printInfo(n);
211 }
212 
213 
Wave & getWave(int &key)
Get the wave corresponding to a given key.
Definition: scale.cpp:57
Class holding the sampled sound for one key.
Definition: wave.h:49
static constexpr int N
Maximal number of waves in a scale.
Definition: scale.h:72
Voice - a set of scales, keeping the acoustic data of an instrument.
Definition: voice.h:39
bool read(QIODevice &iodevice, Voice *voice=nullptr)
Read data of a scale from a device.
Definition: scale.cpp:176
Scale()
Constructor, creates N=128 empty wave objects.
Definition: scale.cpp:44
const int ctag
Tag to recognize a scale in a file.
Definition: scale.h:73
bool write(QIODevice &iodevice, Voice *voice=nullptr)
Write scale to device.
Definition: scale.cpp:145
void printInfo()
Scale::printInfo.
Definition: scale.cpp:207
void generateArtificialSound(Voice *voice=nullptr, int samplerate=44100)
Generate a scale of artificial sounds in equal temperament.
Definition: scale.cpp:70
bool insert(const int key, const QVector< qint32 > &L, const QVector< qint32 > &R, const bool release, const double amplification)
Insert a newly recorded or generated waveform into the scale. This function checks the parameters and...
Definition: scale.cpp:103
static bool read(QIODevice &iodevice, const T &object)
void setProgress(QVariant percent)
bool mCancellationRequested
Cancel loading.
Definition: scale.h:74
QVector< Wave > mWaves
This is the actual vector of waves.
Definition: scale.h:71
static bool write(QIODevice &iodevice, const T &object)