reversound/src/conteneurs/NoteGamme.java
2014-06-16 16:48:34 +02:00

268 lines
6.7 KiB
Java

/*
Reversound is used to get the music sheet of a piece from a music file.
Copyright (C) 2014 Gabriel AUGENDRE
Copyright (C) 2014 Gabriel DIENY
Copyright (C) 2014 Arthur GAUCHER
Copyright (C) 2014 Gabriel LEPETIT-AIMON
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package conteneurs;
import java.util.ArrayList;
/**
* Created by Gabriel on 16/04/2014.
* Gamme qui ne garde que les fréquences qui correspondent à des notes utilisées dans les gammes classiques tempérées
*/
public class NoteGamme extends Gamme {
static final float MAX_FREQ = 2100;
static final float MIN_FREQ = 18.354002f;
private ArrayList<Float> freqID;
private NoteGamme(){
this.freqID = new ArrayList<Float>();
}
private static NoteGamme noteGamme = new NoteGamme();
public static NoteGamme gamme(){
return noteGamme;
}
/** public void computeFreqNote(){
/**for(float freq = 440; freq < this.MAX_FREQ; freq = freq*(float)Math.pow(2, 1/12.0) ){
this.freqID.addNote(freq);
System.out.println(freqID.get(freqID.size()-1));
}
for(float freq = 440; freq > MIN_FREQ; freq = freq/(float)Math.pow(2,1/12.0)){
this.freqID.addNote(0,freq);
System.out.println(freqID.get(0));
}
System.out.println(freqID.size());
for(float f = MIN_FREQ; f < MAX_FREQ; f = f*(float)Math.pow(2, 1/12.0)){
freqID.addNote(f);
System.out.println(f);
}
} */
@Override
public ArrayList<Number> getIndex(float freq) {
return getStatIndex(freq);
}
public static ArrayList<Number> getStatIndex(float freq){
ArrayList<Number> res = new ArrayList<>();
// Gère le cas où on demande une fréquence qui n'est pas comprise entre le minimum et le maximum des fréquences de cette gamme.
if(freq < MIN_FREQ ||freq > MAX_FREQ){
res.add(-1);
return res;
}
//Cherche l'indice du dessus
float f = MIN_FREQ;
int index = 0;
while(f <= freq){
f = f * (float)Math.pow(2, 1/12.0);
index++;
}
//Calcul du coefficient d'interpolation: 0 si freq = fréquence inférieure, 1 si freq = freq supérieure
float coeff = (freq - (f/(float)Math.pow(2,1/12.0)))/(f - (f/(float)Math.pow(2,1/12.0)));
res.add(index-1);
res.add(index);
res.add(coeff);
return res;
}
/** Renvoie l'indice de la note a partir de son nom
* @param name son nom en tant que chaine de caractere
* @return l'indice de la note */
public static int getIndex(String name){
int id = ('0'+name.charAt(name.length()-1))*12;
if(name.startsWith("RE#"))
id+=1;
else if(name.startsWith("MI"))
id+=2;
else if(name.startsWith("FA"))
id+=3;
else if(name.startsWith("FA#"))
id+=4;
else if(name.startsWith("SOL"))
id+=5;
else if(name.startsWith("SOL#"))
id+=6;
else if(name.startsWith("LA"))
id+=7;
else if(name.startsWith("LA#"))
id+=8;
else if(name.startsWith("SI"))
id+=9;
else if(name.startsWith("DO"))
id+=10;
else if(name.startsWith("DO#"))
id+=11;
return id;
}
@Override
public float getFreq(int index) {
return getStatFreq(index);
}
public static float getStatFreq(int index){
return MIN_FREQ * (float)Math.pow(2,index/12.0);
}
@Override
public int gammeSize() {
return gammeStatSize();
}
public static int gammeStatSize(){
int size = 0;
for(float f = MIN_FREQ; f < MAX_FREQ; f = f*(float)Math.pow(2,1/12.0)){
size ++;
}
return size;
}
/** Renvoie le nom d'une note en fonction de la fréquence
* Si la fréquence n'est pas proche d'une note (coeff < 5%), l'indice renvoyé est -1
* @param freq la fréquence dont on cherche la note qui correspond
* @return le nom de la note
*/
public static String getNoteName(float freq){
ArrayList<Number> res = getStatIndex(freq);
int index = -1;
float coeff = (float)res.get(2);
if(coeff < 0.05){
index = (int)res.get(0);
} else if (coeff > 0.95){
index = (int)res.get(1);
}
if(index != -1)
return getNoteName(index);
return null;
}
/** Renvoie la note en fonction de l'indice de la note, (indice 0 : RE) */
public static String getNoteName(int index){
String noteName = "";
if (index >= gammeStatSize() || index <0)
return null;
int octave = (index/12);
index = index%12;
switch(index){
case 0: noteName = "RE";
break;
case 1: noteName = "RE#";
break;
case 2: noteName = "MI";
break;
case 3: noteName = "FA";
break;
case 4: noteName = "FA#";
break;
case 5: noteName = "SOL";
break;
case 6: noteName = "SOL#";
break;
case 7: noteName = "LA";
break;
case 8: noteName = "LA#";
break;
case 9: noteName = "SI";
break;
case 10: noteName = "DO";
octave++;
break;
case 11: noteName = "DO#";
octave++;
break;
}
noteName = noteName + octave;
return noteName;
}
/** Renvoie le nom de la note en version anglaise */
public static String getEnglishNoteName(int index){
String noteName = "";
if (index >= gammeStatSize() || index <0)
return null;
int octave = (index/12);
index = index%12;
switch(index){
case 0: noteName = "d";
break;
case 1: noteName = "dis";
break;
case 2: noteName = "e";
break;
case 3: noteName = "f";
break;
case 4: noteName = "fis";
break;
case 5: noteName = "g";
break;
case 6: noteName = "gis";
break;
case 7: noteName = "a";
break;
case 8: noteName = "ais";
break;
case 9: noteName = "b";
break;
case 10: noteName = "c";
octave++;
break;
case 11: noteName = "cis";
octave++;
break;
}
for (int i = 3; i < octave; i++)
noteName+="\'";
return noteName;
}
/** Renvoie la frequence maximale de la NoteGamme */
public static float getMaxFreq() {
return MAX_FREQ;
}
/** Renvoie la frequence minimale de la NoteGamme */
public static float getMinFreq() {
return MIN_FREQ;
}
@Override
public ArrayList<String> toStringList(){
ArrayList<String> r = new ArrayList<>(gammeSize());
for (int i = 0; i < gammeSize(); i++)
r.add(String.valueOf(getNoteName(i)));
return r;
}
}