rendered paste bodyimport javax.swing.*; //GUIimport javax.swing.event.*; //ChangeListenerimport java.awt.*; //GridLayout e Dimensionimport java.awt.event.*; //ActionListenerimport javax.sound.sampled.*; //Audioimport java.io.*; //Input Output//import java.nio.channels.*;import java.nio.*; //Buffer//import java.util.*;public class FMSynth extends JFrame { AudioFormat formatoAudio; AudioInputStream streamInputAudio; SourceDataLine dataLineSorgente; //-----------------------------------------// //Parametri audio //-----------------------------------------// float FREQ_CAMPIONAMENTO = 44100.0F; //Altri possibili: 8000,11025,16000,22050,44100 int DIM_CAMPIONE_BIT = 16; //Bit, possibili: 8,16 int NUM_CANALI = 1; //Possibili 1,2 boolean SIGNED = true; //Possibili true,false boolean BIG_ENDIAN = true; //Possibili true,false int tempo_MAX = 60; int DIM_MAX_CAMPIONE_BYTE = (tempo_MAX * DIM_CAMPIONE_BIT)/8; int FREQ_CAMPIONAMENTO_INT = (int)FREQ_CAMPIONAMENTO; byte audioData[] = new byte[FREQ_CAMPIONAMENTO_INT * DIM_MAX_CAMPIONE_BYTE]; //-----------------------------------------// //GUI //-----------------------------------------// //Valori di inizializzazione degli oggetti GUI int FREQ_SLIDER_C_MIN = 0; int FREQ_SLIDER_C_MAX = 10000; int FREQ_SLIDER_C_VALUE = 440; int AMP_SLIDER_MIN = 0; int AMP_SLIDER_MAX = 100; int AMP_SLIDER_VALUE = 50; int FREQ_SLIDER_M_MIN = 0; int FREQ_SLIDER_M_MAX = 10000; int FREQ_SLIDER_M_VALUE = 440; int INDEX_SLIDER_MIN = 0; int INDEX_SLIDER_MAX = 200; int INDEX_SLIDER_VALUE = 50; int DUR_SLIDER_MIN = 0; int DUR_SLIDER_MAX = 60; int DUR_SLIDER_VALUE = 2; int VOL_SLIDER_MIN = 0; int VOL_SLIDER_MAX = 16000; int VOL_SLIDER_VALUE = 10000; //upPanel final JLabel carrierLabel = new JLabel("Carrier"); final JLabel ampLabel = new JLabel("Amplitude"); final JLabel modLabel = new JLabel("Modulator"); final JLabel indexLabel = new JLabel("Index"); final JLabel timeLabel = new JLabel("Duration"); final JSlider freqSliderC = new JSlider(JSlider.HORIZONTAL, FREQ_SLIDER_C_MIN, FREQ_SLIDER_C_MAX, FREQ_SLIDER_C_VALUE); final JLabel freqLabelC = new JLabel(freqSliderC.getValue()+"Hz"); final JSlider ampSlider = new JSlider(JSlider.HORIZONTAL, AMP_SLIDER_MIN, AMP_SLIDER_MAX, AMP_SLIDER_VALUE); final JLabel ampLabelC = new JLabel(ampSlider.getValue()+"%"); //WaveformPanel portante final JRadioButton sineRadioC = new JRadioButton("Sine", true); final JRadioButton squareRadioC = new JRadioButton("Sqr"); final JRadioButton triRadioC = new JRadioButton("Tri"); final JRadioButton sawRadioC = new JRadioButton("Saw"); final JLabel waveformLabelC = new JLabel("Waveform"); final JSlider freqSliderM = new JSlider(JSlider.HORIZONTAL, FREQ_SLIDER_M_MIN, FREQ_SLIDER_M_MAX, FREQ_SLIDER_M_VALUE); final JLabel freqLabelM = new JLabel(freqSliderM.getValue()+"Hz"); final JSlider indexSlider = new JSlider(JSlider.HORIZONTAL, INDEX_SLIDER_MIN, INDEX_SLIDER_MAX, INDEX_SLIDER_VALUE); final JLabel indexLabelM = new JLabel(indexSlider.getValue()+"%"); //WaveformPanel modulante final JRadioButton sineRadioM = new JRadioButton("Sine", true);; final JRadioButton squareRadioM = new JRadioButton("Sqr"); final JRadioButton triRadioM = new JRadioButton("Tri"); final JRadioButton sawRadioM = new JRadioButton("Saw"); final JLabel waveformLabelM = new JLabel("Waveform"); //downPanel final JSlider durSlider = new JSlider(JSlider.HORIZONTAL, DUR_SLIDER_MIN, DUR_SLIDER_MAX, DUR_SLIDER_VALUE); final JLabel durLabel = new JLabel(durSlider.getValue()+"s"); final JToggleButton synthButton = new JToggleButton("Synthesize"); final JToggleButton listenFileButton = new JToggleButton("Listen/File"); //outputPanel final JRadioButton listenRadio = new JRadioButton("Listen", true); final JRadioButton fileRadio = new JRadioButton("File"); final JTextField fileName = new JTextField("Generated"); final JLabel outputLabel = new JLabel("Output"); //RightPanel final JSlider volSlider = new JSlider(JSlider.VERTICAL, VOL_SLIDER_MIN, VOL_SLIDER_MAX, VOL_SLIDER_VALUE); final JLabel volLabel = new JLabel("Master"); //CommentPanel final JLabel commentLabel = new JLabel("Frequency Modulation Syntheziser, ©2008 Giovanni Bedetti, STI"); //-----------------------------------------// //Main //-----------------------------------------// public static void main(String args[]) { new FMSynth(); } //-----------------------------------------// //Costruttore //-----------------------------------------// public FMSynth() { //fullPanel final JPanel fullPanel = new JPanel(); //centerPanel final JPanel centerPanel = new JPanel(); centerPanel.setBorder(BorderFactory.createEtchedBorder()); //upPanel final JPanel upPanel = new JPanel(); upPanel.setBorder(BorderFactory.createEtchedBorder()); upPanel.setLayout(new GridLayout(5,0)); //sliderPanelC final JPanel sliderPanelC = new JPanel(); sliderPanelC.setBorder(BorderFactory.createEtchedBorder()); //ampWavePanelC final JPanel ampWavePanelC = new JPanel(); ampWavePanelC.setBorder(BorderFactory.createEtchedBorder()); //waveformPanelC final JPanel waveformPanelC = new JPanel(); final ButtonGroup waveformPanelCButtonGroup = new ButtonGroup(); waveformPanelC.setBorder(BorderFactory.createEtchedBorder()); //sliderPanelM final JPanel sliderPanelM = new JPanel(); sliderPanelM.setBorder(BorderFactory.createEtchedBorder()); //indexWavePanelM final JPanel indexWavePanelM = new JPanel(); indexWavePanelM.setBorder(BorderFactory.createEtchedBorder()); //waveformPanelM final JPanel waveformPanelM = new JPanel(); final ButtonGroup waveformPanelMButtonGroup = new ButtonGroup(); waveformPanelM.setBorder(BorderFactory.createEtchedBorder()); //downPanel final JPanel downPanel = new JPanel(); downPanel.setBorder(BorderFactory.createEtchedBorder()); downPanel.setLayout(new GridLayout(2,0)); //outputPanel final JPanel outputPanel = new JPanel(); outputPanel.setBorder(BorderFactory.createEtchedBorder()); //listenFilePanel final JPanel listenFilePanel = new JPanel(); final ButtonGroup listenFilePanelButtonGroup = new ButtonGroup(); //largeButtonPanel final JPanel largeButtonPanel = new JPanel(); //commentPanel final JPanel commentPanel = new JPanel(); //rightPanel final JPanel rightPanel = new JPanel(); //Bottone per l'ascolto inizialmente disabilitato //per forzare l'utente a generare un segnale //prima di provare ad ascoltarlo o salvarlo su file listenFileButton.setEnabled(false); //Aggiungiamo un ActionListener al bottone di generazione synthButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { //Bottone per l'ascolto disabilitato per //impedire l'ascolto durante la generazione listenFileButton.setEnabled(false); new Generatore().Genera(audioData); listenFileButton.setEnabled(true); } } ); //Aggiungiamo un ActionListener al bottone di ascolto/salvataggio file listenFileButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { AscoltaSalvaData(); } } ); //Aggiungiamo i ChangeListeners per avere nelle labels i valori degli sliders freqSliderC.addChangeListener ( new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider freqSliderC = (JSlider)e.getSource(); freqLabelC.setText(freqSliderC.getValue()+"Hz"); } } ); ampSlider.addChangeListener ( new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider ampSlider = (JSlider)e.getSource(); ampLabelC.setText(ampSlider.getValue()+"%"); } } ); freqSliderM.addChangeListener ( new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider freqSliderM = (JSlider)e.getSource(); freqLabelM.setText(freqSliderM.getValue()+"Hz"); } } ); indexSlider.addChangeListener ( new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider indexSlider = (JSlider)e.getSource(); indexLabelM.setText(indexSlider.getValue()+"%"); } } ); durSlider.addChangeListener ( new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider durSlider = (JSlider)e.getSource(); durLabel.setText(durSlider.getValue()+"s"); } } ); //Aggiungiamo i vari pannelli al pannello principale fullPanel.add(centerPanel); fullPanel.add(rightPanel); //Aggiungiamo il pannello in alto, quello in basso e quello di commento //al pannello centrale centerPanel.add(upPanel); centerPanel.add(downPanel); //Aggiungiamo gli oggetti grafici al pannello in alto upPanel.add(sliderPanelC); sliderPanelC.add(carrierLabel); sliderPanelC.add(freqSliderC); sliderPanelC.add(freqLabelC); upPanel.add(ampWavePanelC); ampWavePanelC.add(ampLabel); ampWavePanelC.add(ampSlider); ampWavePanelC.add(ampLabelC); ampWavePanelC.add(waveformPanelC); waveformPanelC.add(sineRadioC); waveformPanelC.add(squareRadioC); waveformPanelC.add(triRadioC); waveformPanelC.add(sawRadioC); waveformPanelC.add(waveformLabelC); upPanel.add(sliderPanelM); sliderPanelM.add(modLabel); sliderPanelM.add(freqSliderM); sliderPanelM.add(freqLabelM); upPanel.add(indexWavePanelM); indexWavePanelM.add(indexLabel); indexWavePanelM.add(indexSlider); indexWavePanelM.add(indexLabelM); indexWavePanelM.add(waveformPanelM); waveformPanelM.add(sineRadioM); waveformPanelM.add(squareRadioM); waveformPanelM.add(triRadioM); waveformPanelM.add(sawRadioM); waveformPanelM.add(waveformLabelM); upPanel.add(outputPanel); //Aggiungiamo i bottoni di selezione della forma d'onda a un gruppo //per ottenere la scelta esclusiva //portante waveformPanelCButtonGroup.add(sineRadioC); waveformPanelCButtonGroup.add(squareRadioC); waveformPanelCButtonGroup.add(triRadioC); waveformPanelCButtonGroup.add(sawRadioC); //modulante waveformPanelMButtonGroup.add(sineRadioM); waveformPanelMButtonGroup.add(squareRadioM); waveformPanelMButtonGroup.add(triRadioM); waveformPanelMButtonGroup.add(sawRadioM); //Aggiungiamo gli oggetti grafici al pannello in basso //downPanel.add(outputPanel); //outputPanel outputPanel.add(timeLabel); outputPanel.add(durSlider); outputPanel.add(durLabel); outputPanel.add(listenFilePanel); //listenFilePanel listenFilePanel.add(listenRadio); listenFilePanel.add(fileRadio); listenFilePanelButtonGroup.add(listenRadio); listenFilePanelButtonGroup.add(fileRadio); listenFilePanel.add(fileName); listenFilePanel.add(outputLabel); downPanel.add(largeButtonPanel); largeButtonPanel.add(synthButton); largeButtonPanel.add(listenFileButton); downPanel.add(commentPanel); //Aggiungiamo il commento al pannello di commento commentPanel.add(commentLabel); //Aggiungiamo lo slider al pannello di destra rightPanel.add(volSlider); rightPanel.add(volLabel); //Disponiamo i pannelli nello spazio della GUI getContentPane().add(centerPanel, BorderLayout.CENTER); getContentPane().add(rightPanel, BorderLayout.EAST); //setContentPane(new JLabel(new ImageIcon("/Users/giovi/NetBeansProjects/FmSynth/brushed.jpg"))); carrierLabel.setBorder(BorderFactory.createEtchedBorder()); ampLabel.setBorder(BorderFactory.createEtchedBorder()); modLabel.setBorder(BorderFactory.createEtchedBorder()); indexLabel.setBorder(BorderFactory.createEtchedBorder()); durLabel.setBorder(BorderFactory.createEtchedBorder()); freqSliderC.setBorder(BorderFactory.createEtchedBorder()); ampSlider.setBorder(BorderFactory.createEtchedBorder()); freqSliderM.setBorder(BorderFactory.createEtchedBorder()); indexSlider.setBorder(BorderFactory.createEtchedBorder()); durSlider.setBorder(BorderFactory.createEtchedBorder()); ampLabelC.setBorder(BorderFactory.createEtchedBorder()); waveformLabelC.setBorder(BorderFactory.createEtchedBorder()); waveformLabelM.setBorder(BorderFactory.createEtchedBorder()); outputLabel.setBorder(BorderFactory.createEtchedBorder()); freqLabelC.setBorder(BorderFactory.createEtchedBorder()); freqLabelM.setBorder(BorderFactory.createEtchedBorder()); indexLabelM.setBorder(BorderFactory.createEtchedBorder()); timeLabel.setBorder(BorderFactory.createEtchedBorder()); listenFilePanel.setBorder(BorderFactory.createEtchedBorder()); downPanel.setBorder(BorderFactory.createEtchedBorder()); largeButtonPanel.setBorder(BorderFactory.createEtchedBorder()); commentPanel.setBorder(BorderFactory.createEtchedBorder()); rightPanel.setBorder(BorderFactory.createEtchedBorder()); volSlider.setBorder(BorderFactory.createEtchedBorder()); volLabel.setBorder(BorderFactory.createEtchedBorder()); //Settiamo le dimensioni degli oggetti carrierLabel.setPreferredSize(new Dimension(100, 20)); ampLabel.setPreferredSize(new Dimension(100, 20)); modLabel.setPreferredSize(new Dimension(100, 20)); indexLabel.setPreferredSize(new Dimension(100, 20)); timeLabel.setPreferredSize(new Dimension(100, 20)); // freqSliderC.setPreferredSize(new Dimension(500, 35)); freqLabelC.setPreferredSize(new Dimension(70, 35)); ampSlider.setPreferredSize(new Dimension(215, 35)); ampLabelC.setPreferredSize(new Dimension(50,35)); freqSliderM.setPreferredSize(new Dimension(500, 35)); freqLabelM.setPreferredSize(new Dimension(70, 35)); indexSlider.setPreferredSize(new Dimension(215, 35)); indexLabelM.setPreferredSize(new Dimension(50,35)); durSlider.setPreferredSize(new Dimension(215, 35)); durLabel.setPreferredSize(new Dimension(50,35)); waveformPanelC.setPreferredSize(new Dimension(300, 35)); waveformPanelM.setPreferredSize(new Dimension(300, 35)); listenFilePanel.setPreferredSize(new Dimension(300, 35)); fileName.setPreferredSize(new Dimension(102, 20)); largeButtonPanel.setPreferredSize(new Dimension(250, 50)); commentLabel.setPreferredSize(new Dimension(400, 35)); volSlider.setPreferredSize(new Dimension(35, 350)); rightPanel.setPreferredSize(new Dimension(50, 355)); upPanel.setPreferredSize(new Dimension(705, 265)); // synthButton.setPreferredSize(new Dimension(120,35)); synthButton.setBackground(new Color(255, 0, 0)); listenFileButton.setPreferredSize(new Dimension(120,35)); listenFileButton.setBackground(new Color(0, 204, 0)); //Ultimi dettagli setTitle("FM Synthesizer"); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(780,410); setVisible(true); setResizable(false); }//Fine del costruttore //-----------------------------------------// //Metodo: AscoltaSalvaData //-----------------------------------------// private void AscoltaSalvaData() { try { //Prendiamo la durata del segnale da generare dal valore impostato sullo slider //e calcoliamo il numero totale di Byte che vogliamo leggere dall'array int Durata = durSlider.getValue(); //Creiamo uno stream di input che contiene gli audioData InputStream byteArrayInputStream = new ByteArrayInputStream(audioData); //Otteniamo il formato audio definito all'inizio formatoAudio = new AudioFormat(FREQ_CAMPIONAMENTO, DIM_CAMPIONE_BIT, NUM_CANALI, SIGNED, BIG_ENDIAN); //Costruiamo un input stream audio che ha il formato richiesto e lunghezza in frames, //usando gli audioData dello stream di input //la lunghezza e' divisa per il tempo massimo e moltiplicata per la durata //cosi da ottenere la lunghezza desiderata dello stream streamInputAudio = new AudioInputStream(byteArrayInputStream, formatoAudio, (audioData.length/formatoAudio.getFrameSize())/tempo_MAX*Durata); //Otteniamo informazioni sulla Data Line richiesta DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, formatoAudio); //Creiamo un oggetto sourceDataLine dataLineSorgente = (SourceDataLine) AudioSystem.getLine(dataLineInfo); //Scegliamo se ascoltare gli audioData subito oppure salvarli in un audiofile //a seconda della selezione fatta dall'utente if(listenRadio.isSelected()) { //Creiamo un thread per riprodurre data e facciamolo partire. //Rimarra' attivo finche' tutto l'audioData sara' stato riprodotto. new ListenThread().start(); } else { //Disabilitiamo i bottoni di generazione e ascolto finche' i data esistenti //non sono stati scritti sul file synthButton.setEnabled(false); listenFileButton.setEnabled(false); //Scriviamo gli audioData nel file che avra' un nome ottenuto //dal text field FileName e, dopo aver scelto il formato, aggiungiamo estensione aif try { AudioSystem.write(streamInputAudio, AudioFileFormat.Type.AIFF, new File(fileName.getText()+".aif")); } //Gestione delle eccezioni catch (Exception e) { e.printStackTrace(); System.exit(0); } //Abilitiamo i bottoni per altre operazioni synthButton.setEnabled(true); listenFileButton.setEnabled(true); } } //Gestione delle eccezioni catch (Exception e) { e.printStackTrace(); System.exit(0); } } //-----------------------------------------// //Classe: ListenThread //-----------------------------------------// //Classe per riprodurre gli audioData class ListenThread extends Thread { //Creiamo un buffer per trasferire data tra l'AudioInputStream e la //SourceDataLine. La dimensione e' arbitraria. byte PlayBuffer[] = new byte[16384]; public void run() { try { //Disabilitiamo i bottoni finche' non cessa la riproduzione synthButton.setEnabled(false); listenFileButton.setEnabled(false); //Apriamo e facciamo partire la SourceDataLine dataLineSorgente.open(formatoAudio); dataLineSorgente.start(); int cnt; //Trasferiamo gli audioData all'uscita audio del sistema //Usciamo dal ciclo solo quando incontriamo il -1 che indica lo stream vuoto while((cnt = streamInputAudio.read(PlayBuffer, 0, PlayBuffer.length)) != -1) { if(cnt > 0) { //Scriviamo data nel buffer interno della DataLine //dove sara' mandato all'uscita audio del sistema //in tempo reale dataLineSorgente.write( PlayBuffer, 0, cnt); } } //Aspettiamo che il buffer interno della SourceDataLine si svuoti dataLineSorgente.drain(); //Fermiamo e chiudiamo la SourceDataLine dataLineSorgente.stop(); dataLineSorgente.close(); //Riabilitiamo i bottoni per altre operazioni synthButton.setEnabled(true); listenFileButton.setEnabled(true); } //Gestione delle eccezioni catch (Exception e) { e.printStackTrace(); System.exit(0); } } } //-----------------------------------------// //Classe: Generatore //-----------------------------------------// //Questa classe contiene due metodi: Genera gestisce i buffer, //Fm si occupa della generazione vera e propria. Ogni volta che //il metodo Genera viene chiamato esso riempie l'array in arrivo con i campioni ottenuti //dal metodo Fm. class Generatore { //Nota: Poiche' questa classe usa un ByteBuffer come ShortBuffer per maneggiare //gli audioData puo' essere usata solo per generare data a 16-bit di tipo SIGNED ByteBuffer byteBuffer; ShortBuffer shortBuffer; int lunghezzaByte; //Metodo Genera void Genera(byte[] SynDataBuffer) { //Prepariamo il byteBuffer e lo shortBuffer all'uso byteBuffer = ByteBuffer.wrap(SynDataBuffer); shortBuffer = byteBuffer.asShortBuffer(); lunghezzaByte = SynDataBuffer.length; //Chiamiamo il metodo Fm double freqPortante = (double)freqSliderC.getValue(); double freqModulante = (double)freqSliderM.getValue(); //Ampiezza della portante e indice della modulazione sono divisi per 100 cosi' da indicare il valore percentuale double ampPortante = (double)ampSlider.getValue()/100; double indiceMod = (double)indexSlider.getValue()/100; //Otteniamo il valore del volume double volume = (double)volSlider.getValue(); int waveModulante = 1; int wavePortante = 1; if (sineRadioM.isSelected()) { waveModulante = 1; } else if (squareRadioM.isSelected()) { waveModulante = 2; } else if (triRadioM.isSelected()) { waveModulante = 3; } else if (sawRadioM.isSelected()) { waveModulante = 4; } if (sineRadioC.isSelected()) { wavePortante = 1; } else if (squareRadioC.isSelected()) { wavePortante = 2; } else if (triRadioC.isSelected()) { wavePortante = 3; } else if (sawRadioC.isSelected()) { wavePortante = 4; } FM(freqPortante, freqModulante, ampPortante, indiceMod, wavePortante, waveModulante, volume); } void FM(double freqPortante, //frequenza della portante double freqModulante, //frequenza della modulante double ampPortante, //ampiezza della portante double indiceMod, //indice di modulazione int wavePortante, //forma d'onda della portante int waveModulante, //forma d'onda della modulante double volume) //volume generale { NUM_CANALI = 1; //1 = mono, 2 = stereo(qui inutile) FREQ_CAMPIONAMENTO = 44100.0F; //Possibili 8000,11025,16000,22050,44100 int BYTE_PER_CAMPIONE = 2; //16-bit per campione = 2 byte per campione int LUNGHEZZA_GENERAZIONE = lunghezzaByte/BYTE_PER_CAMPIONE; //Ciclo per creare il numero di campioni desiderato. Il ciclo si ripetera' //LUNGHEZZA_GENERAZIONE volte for(int cnt = 0; cnt < LUNGHEZZA_GENERAZIONE; cnt++) { double tempo = cnt/FREQ_CAMPIONAMENTO; double modulante = 0.0; double portante = 0.0; //Generazione della modulante if(indiceMod != 0) { if (waveModulante == 1) //sine { modulante = Math.sin(2*Math.PI*freqModulante*tempo)*indiceMod; } else if (waveModulante == 2) //square { modulante = Math.signum(Math.sin(2*Math.PI*freqModulante*tempo))*indiceMod; } else if (waveModulante == 3) //triangle { modulante = (Math.sin(2*Math.PI*freqModulante*tempo)- Math.sin(2*Math.PI*freqModulante*3*tempo)/9- Math.sin(2*Math.PI*freqModulante*5*tempo)/25- Math.sin(2*Math.PI*freqModulante*7*tempo)/49- Math.sin(2*Math.PI*freqModulante*9*tempo)/81- Math.sin(2*Math.PI*freqModulante*11*tempo)/121- Math.sin(2*Math.PI*freqModulante*13*tempo)/169- Math.sin(2*Math.PI*freqModulante*15*tempo)/225- Math.sin(2*Math.PI*freqModulante*17*tempo)/289- Math.sin(2*Math.PI*freqModulante*19*tempo)/361- Math.sin(2*Math.PI*freqModulante*21*tempo)/441- Math.sin(2*Math.PI*freqModulante*23*tempo)/529- Math.sin(2*Math.PI*freqModulante*25*tempo)/625- Math.sin(2*Math.PI*freqModulante*27*tempo)/729- Math.sin(2*Math.PI*freqModulante*29*tempo)/841- Math.sin(2*Math.PI*freqModulante*31*tempo)/961- Math.sin(2*Math.PI*freqModulante*33*tempo)/1089- Math.sin(2*Math.PI*freqModulante*35*tempo)/1225- Math.sin(2*Math.PI*freqModulante*37*tempo)/1369) *indiceMod; } else if (waveModulante == 4) //sawtooth { modulante = (Math.sin(2*Math.PI*freqModulante*tempo)+ Math.sin(2*Math.PI*freqModulante*2*tempo)/2+ Math.sin(2*Math.PI*freqModulante*3*tempo)/3+ Math.sin(2*Math.PI*freqModulante*4*tempo)/4+ Math.sin(2*Math.PI*freqModulante*5*tempo)/5+ Math.sin(2*Math.PI*freqModulante*6*tempo)/6+ Math.sin(2*Math.PI*freqModulante*7*tempo)/7+ Math.sin(2*Math.PI*freqModulante*8*tempo)/8+ Math.sin(2*Math.PI*freqModulante*9*tempo)/9+ Math.sin(2*Math.PI*freqModulante*10*tempo)/10+ Math.sin(2*Math.PI*freqModulante*11*tempo)/11+ Math.sin(2*Math.PI*freqModulante*12*tempo)/12+ Math.sin(2*Math.PI*freqModulante*13*tempo)/13+ Math.sin(2*Math.PI*freqModulante*14*tempo)/14+ Math.sin(2*Math.PI*freqModulante*15*tempo)/15+ Math.sin(2*Math.PI*freqModulante*16*tempo)/16+ Math.sin(2*Math.PI*freqModulante*17*tempo)/17+ Math.sin(2*Math.PI*freqModulante*18*tempo)/18+ Math.sin(2*Math.PI*freqModulante*19*tempo)/19) *indiceMod; } } //Generazione della portante if (ampPortante != 0) { if (wavePortante == 1) //sine { portante = Math.sin(2*Math.PI*freqPortante*tempo+modulante)*ampPortante; } else if (wavePortante == 2) //square { portante = Math.signum(Math.sin((2*Math.PI*freqPortante*tempo)+modulante)) *ampPortante; } else if (wavePortante == 3) //triangle { /*portante = (Math.sin(2*Math.PI*freqportante*tempo)- Math.sin(2*Math.PI*freqportante*3*tempo)/9- Math.sin(2*Math.PI*freqportante*5*tempo)/25- Math.sin(2*Math.PI*freqportante*7*tempo)/49- Math.sin(2*Math.PI*freqportante*9*tempo)/81- Math.sin(2*Math.PI*freqportante*11*tempo)/121- Math.sin(2*Math.PI*freqportante*13*tempo)/169- Math.sin(2*Math.PI*freqportante*15*tempo)/225- Math.sin(2*Math.PI*freqportante*17*tempo)/289- Math.sin(2*Math.PI*freqportante*19*tempo)/361- Math.sin(2*Math.PI*freqportante*21*tempo)/441- Math.sin(2*Math.PI*freqportante*23*tempo)/529- Math.sin(2*Math.PI*freqportante*25*tempo)/625- Math.sin(2*Math.PI*freqportante*27*tempo)/729- Math.sin(2*Math.PI*freqportante*29*tempo)/841- Math.sin(2*Math.PI*freqportante*31*tempo)/961- Math.sin(2*Math.PI*freqportante*33*tempo)/1089- Math.sin(2*Math.PI*freqportante*35*tempo)/1225- Math.sin(2*Math.PI*freqportante*37*tempo)/1369+ modulante) *ampportante;*/ //-------------------// //this one! //-------------------// double a=freqPortante*FREQ_CAMPIONAMENTO; portante = (Math.abs(tempo-Math.floor(tempo/a)*a-0.5)); } else if (wavePortante == 4) { portante = Math.sin((2*Math.PI*freqPortante*tempo)+ Math.sin(2*Math.PI*freqPortante*2*tempo)/2+ Math.sin(2*Math.PI*freqPortante*3*tempo)/3+ Math.sin(2*Math.PI*freqPortante*4*tempo)/4+ Math.sin(2*Math.PI*freqPortante*5*tempo)/5+ Math.sin(2*Math.PI*freqPortante*6*tempo)/6+ Math.sin(2*Math.PI*freqPortante*7*tempo)/7+ Math.sin(2*Math.PI*freqPortante*8*tempo)/8+ Math.sin(2*Math.PI*freqPortante*9*tempo)/9+ Math.sin(2*Math.PI*freqPortante*10*tempo)/10+ Math.sin(2*Math.PI*freqPortante*11*tempo)/11+ Math.sin(2*Math.PI*freqPortante*12*tempo)/12+ Math.sin(2*Math.PI*freqPortante*13*tempo)/13+ Math.sin(2*Math.PI*freqPortante*14*tempo)/14+ Math.sin(2*Math.PI*freqPortante*15*tempo)/15+ Math.sin(2*Math.PI*freqPortante*16*tempo)/16+ Math.sin(2*Math.PI*freqPortante*17*tempo)/17+ Math.sin(2*Math.PI*freqPortante*18*tempo)/18+ Math.sin(2*Math.PI*freqPortante*19*tempo)/19+ modulante) *ampPortante; }// Fine if }//Fine generazione portante //Inseriamo la portante(modulata o non) nel Buffer shortBuffer.put((short)(portante*volume)); }//Fine del ciclo di generazione }//Fine metodo Fm }//Fine Generatore}//Fine FMSynth