/*
*
      
_______
                       
_____
   
_____ _____
  

*
     
|__
   
__|
                     
|
  
__ \ / ____|__ \
 

*
        
| | __ _ _ __ ___
  
______| || | (___ | |__) |
*
        
| |/ _` | '__/ __|/ _ \/ __| |
  
| |\___ \|___/
 

*
        
| | (_| | |
  
\__ \ (_) \__ \ |__| |____) | |
     

*
        
|_|\__,_|_|
  
|___/\___/|___/_____/|_____/|_|
     

*
                                                         

* -------------------------------------------------------------
*
* TarsosDSP is developed by Joren Six at IPEM, University Ghent
*
  

* -------------------------------------------------------------
*
*
  
Info:
 
http://0110.be/tag/TarsosDSP
*
  
Github:
 
https://github.com/JorenSix/TarsosDSP
*
  
Releases:
 
http://0110.be/releases/TarsosDSP/
*
  

*
  
TarsosDSP includes modified source code by various authors,
*
  
for credits and info, see README.
*
 

*/


package be.tarsos.dsp.pitch;

/**
 
* Utility class to generate Dual-tone multi-frequency (DTMF) signaling tones.
 
* This class also contains a list of valid DTMF frequencies and characters.
 
*
 
* See the <a href=" http://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling"
 
* >WikiPedia article on DTMF</a>.
 
*
 
* @author Joren Six
 
*/

public class DTMF {

	
/**
	 
* The list of valid DTMF frequencies. See the <a
	 
* href=" http://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling"
	 
* >WikiPedia article on DTMF</a>.
	 
*/

	
public static final double[] DTMF_FREQUENCIES = { 697, 770, 852, 941, 1209,
			
1336, 1477, 1633 };

	
/**
	 
* The list of valid DTMF characters. See the <a
	 
* href=" http://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling"
	 
* >WikiPedia article on DTMF</a> for the relation between the characters
	 
* and frequencies.
	 
*/

	
public static final char[][] DTMF_CHARACTERS = { { '1', '2', '3', 'A' },
			
{ '4', '5', '6', 'B' }, { '7', '8', '9', 'C' },
			
{ '*', '0', '#', 'D' } };

	
/**
	 
* Generate a DTMF - tone for a valid DTMF character.
 

	 
* @param character a valid DTMF character (present in DTMF_CHARACTERS}
	 
* @return a float buffer of predefined length (7168 samples) with the correct DTMF tone representing the character.
	 
*/

	
public static float[] generateDTMFTone(char character){
		
double firstFrequency = -1;
		
double secondFrequency = -1;
		
for(int row = 0 ; row < DTMF_CHARACTERS.length ; row++){
			
for(int col = 0 ; col < DTMF_CHARACTERS[row].length ; col++){
				
if(DTMF_CHARACTERS[row][col] == character){
					
firstFrequency = DTMF_FREQUENCIES[row];
					
secondFrequency = DTMF_FREQUENCIES[col + 4];
				
}
			
}
		
}
		
return DTMF.audioBufferDTMF(firstFrequency,secondFrequency,512*2*10);
	
}
	

	
/**
	 
* Checks if the given character is present in DTMF_CHARACTERS.
	 
*
 

	 
* @param character
	 
*
            
the character to check.
	 
* @return True if the given character is present in
	 
*
         
DTMF_CHARACTERS, false otherwise.
	 
*/

	
public static boolean isDTMFCharacter(char character){
		
double firstFrequency = -1;
		
double secondFrequency = -1;
		
for(int row = 0 ; row < DTMF_CHARACTERS.length ; row++){
			
for(int col = 0 ; col < DTMF_CHARACTERS[row].length ; col++){
				
if(DTMF_CHARACTERS[row][col] == character){
					
firstFrequency = DTMF_FREQUENCIES[row];
					
secondFrequency = DTMF_FREQUENCIES[col + 4];
				
}
			
}
		
}
		
return (firstFrequency!=-1 && secondFrequency!=-1);
	
}

	
/**
	 
* Creates an audio buffer in a float array of the defined size. The sample
	 
* rate is 44100Hz by default. It mixes the two given frequencies with an
	 
* amplitude of 0.5.
	 
*
 

	 
* @param f0
	 
*
            
The first fundamental frequency.
	 
* @param f1
	 
*
            
The second fundamental frequency.
	 
* @param size
	 
*
            
The size of the float array (sample rate is 44.1kHz).
	 
* @return An array of the defined size.
	 
*/

	
public static float[] audioBufferDTMF(final double f0, final double f1,
			
int size) {
		
final double sampleRate = 44100.0;
		
final double amplitudeF0 = 0.4;
		
final double amplitudeF1 = 0.4;
		
final double twoPiF0 = 2 * Math.PI * f0;
		
final double twoPiF1 = 2 * Math.PI * f1;
		
final float[] buffer = new float[size];
		
for (int sample = 0; sample < buffer.length; sample++) {
			
final double time = sample / sampleRate;
			
double f0Component = amplitudeF0 * Math.sin(twoPiF0 * time);
		    
double f1Component = amplitudeF1 * Math.sin(twoPiF1 * time);
		    
buffer[sample] = (float) (f0Component + f1Component);
		
}
		
return buffer;
	
}
}