public class MainActivity extends AppCompatActivity {
AudioTrack audioTrack;
Button bottone;
int minBufferSize=AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_8BIT);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottone=(Button)findViewById(R.id.button);
playSound(440,10);
}
private void playSound(double frequency, int duration) {
// AudioTrack definition
int mBufferSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_8BIT);
AudioTrack mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
mBufferSize, AudioTrack.MODE_STREAM);
// Sine wave
double[] mSound = new double[1000000];
short[] mBuffer = new short[1000000];
for (int i = 0; i < mSound.length; i++) {
mSound[i] = Math.sin((2.0*Math.PI * i/(44100/frequency)));
mBuffer[i] = (short) (mSound[i]*Short.MAX_VALUE);
}
mAudioTrack.setStereoVolume(AudioTrack.getMaxVolume(), AudioTrack.getMaxVolume());
mAudioTrack.play();
mAudioTrack.write(mBuffer, 0, mSound.length);
mAudioTrack.stop();
mAudioTrack.release();
}
}
Bene. Me lo salvo e poi vedrò come utilizzarlo.
Miei appunti liberi, senza pretesa di dire necessariamente sempre cose giuste o sensate, durante l'apprendimento e la pratica della programmazione
JavascriptProva
Visualizzazione post con etichetta .AudioTrack. Mostra tutti i post
Visualizzazione post con etichetta .AudioTrack. Mostra tutti i post
giovedì 17 novembre 2016
440 Hz audioTrack
Ecco il codice per l'emissione di un LA (440 Hz):
martedì 15 novembre 2016
Audiotrack: per far emettere toni puri al cellulare.
Ora proviamo a costruire un dispositivo che emetta una frequenza sonora.
Dobbiamo costruire la classe AndroidAudioDevice.
Ci provo.
Dichiariamo intanto le due variabili, l'una che mi sembra la più importante, di tipo AudioTrack, e l'altra che è una matrice di short, il buffer.
Ora c'è il costruttore, in cui: si ottiene un int minSize, che dovrebbe essere la minima dimensione del buffer.
Vediamolo
Ora bisognerebbe creare il metodo writeSamples che ha per parametri un array di float.
Provo...
Quindi scrive su track quello che legge sul buffer che è "di ritorno" da fillBuffer.
Mi riscrivo qui il codice completo:
Dobbiamo costruire la classe AndroidAudioDevice.
Ci provo.
Dichiariamo intanto le due variabili, l'una che mi sembra la più importante, di tipo AudioTrack, e l'altra che è una matrice di short, il buffer.
class AndroidAudioDevice{
AudioTrack track;
short[] buffer = new short[1024];
}
Bene. E ora?Ora c'è il costruttore, in cui: si ottiene un int minSize, che dovrebbe essere la minima dimensione del buffer.
Vediamolo
class AndroidAudioDevice{
AudioTrack track;
short[] buffer = new short[1024];
int minSize=AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
}
Quindi si definisce track:
public AndroidAudioDevice() {
int minSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.STREAM_MUSIC,
44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minSize,
AudioTrack.MODE_STREAM);
track.play();
}
Aggiungo track.play() ed ecco tutto il costruttore.
Ora bisognerebbe creare il metodo writeSamples che ha per parametri un array di float.
Provo...
public void writeSamples(float[] samples){
fillBuffer(samples);
}
Questo passa subito al metodo privato fillBuffer (che ancora non esiste) il suo parametro array di float.Quindi scrive su track quello che legge sul buffer che è "di ritorno" da fillBuffer.
public void writeSamples(float[] samples){
fillBuffer(samples);
track.write(buffer,0,samples.length);
}
E ora resta da definire fillBuffer.
private void fillBuffer(float[] samples){
}
nel quale prima si adeguano le dimensioni del buffer all'array di samples.
private void fillBuffer(float[] samples){
if(buffer.length < samples.length){
buffer=new short[samples.length];
}
}
e quindi si prendono uno per uno tutti i float di samples e si convertono in short per trasferirli nell'array di short che è buffer.
for(int i=0;i<samples.length;i++){
buffer[i]=(short)(samples[i]*Short.MAX_VALUE);
}
Ecco.Mi riscrivo qui il codice completo:
public class MainActivity extends AppCompatActivity {
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
class AndroidAudioDevice{
AudioTrack track;
short[] buffer = new short[1024];
public AndroidAudioDevice() {
int minSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.STREAM_MUSIC,
44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minSize,
AudioTrack.MODE_STREAM);
track.play();
}
public void writeSamples(float[] samples){
fillBuffer(samples);
track.write(buffer,0,samples.length);
}
private void fillBuffer(float[] samples){
if(buffer.length < samples.length){
buffer=new short[samples.length];
for(int i=0;i<samples.length;i++){
buffer[i]=(short)(samples[i]*Short.MAX_VALUE);
}
}
}
}
}
lunedì 14 novembre 2016
AudioTrack, per far emettere toni allo smartphone. Scontro con i numeri in virgola mobile.
Questo è il link per la riproduzione di toni.
Bisogna costruire una classe AndroidAudioDevice.
Poi si definiscono delle variabili che sono una di tipo AudioTrack e una di tipo matrice di short (short[]).
Quindi il costruttore.
Nel costruttore si definisce minSize (che dovrebbe essere la dimensione minima del buffer).
minsize viene definito usando il metodo AudioTrack.getBufferSize.
Questo deve restituire un int.
Usa come parametri 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT.
44100 è la frequenza di campionamento.
Il secondo parametro è MONO o STEREO.
Il terzo è il formato dei dati, 8 bit o 16 bit o altro (che al momento non mi viene in mente).
Segue il costruttore dell'oggetto di classe AudioTrack specificato fra le variabili iniziali, che usa come parametri il già visto minSize più i parametri che il metodo getMinSize utilizzava, più altri due parametri.
Quindi nel costruttore si dà un valore alla variabile track di classe AudioTrack, e quindi si invoca il metodo play() di questa AudioTrack.
La classe che sto creando, ossia AndroidAudioDevice, oltre al costruttore ha anche il metodo writeSamples().
Vediamolo:
Con le prime due righe...
quindi per ogni elemento contenuto nella matrice samples si prende un elemento del buffer e gli si dà il valore, castato a short, del corrispondente elemento di samples moltiplicato per Short.MAX_VALUE.
Cosa significa questo Short.MAX_VALUE?
Viene moltiplicato un tipo float per Short.MAX_VALUE.
Vediamo se riesco a trovare qualche ispirazione cercando intorno alla conversione short -> float.
Per capire tutto questo forse devo ripassarmi bene come sono strutturati i numeri in virgola mobile.
Quando io moltiplico un float per uno short, lo short viene preventivamente convertito in float?
Se do a uno short un valore superiore al suo massimo, che valore assume la variabile?
Vediamo...
Mi devo costruire dei modelli.
Ecco, come ricordavo, la moltiplicazione di un float per uno short dà un risultato di tipo float.
Ora è il caso di ripassare a dovere i numeri in virgola mobile, perché credo che una risposta mi può venire solo da lì.
Bisogna costruire una classe AndroidAudioDevice.
Poi si definiscono delle variabili che sono una di tipo AudioTrack e una di tipo matrice di short (short[]).
Quindi il costruttore.
Nel costruttore si definisce minSize (che dovrebbe essere la dimensione minima del buffer).
minsize viene definito usando il metodo AudioTrack.getBufferSize.
Questo deve restituire un int.
Usa come parametri 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT.
44100 è la frequenza di campionamento.
Il secondo parametro è MONO o STEREO.
Il terzo è il formato dei dati, 8 bit o 16 bit o altro (che al momento non mi viene in mente).
Segue il costruttore dell'oggetto di classe AudioTrack specificato fra le variabili iniziali, che usa come parametri il già visto minSize più i parametri che il metodo getMinSize utilizzava, più altri due parametri.
Quindi nel costruttore si dà un valore alla variabile track di classe AudioTrack, e quindi si invoca il metodo play() di questa AudioTrack.
La classe che sto creando, ossia AndroidAudioDevice, oltre al costruttore ha anche il metodo writeSamples().
public void writeSamples(float[] samples)
{
fillBuffer( samples );
track.write( buffer, 0, samples.length );
}
Questo metodo ha come parametro una matrice di tipo float[] e la usa come parametro del metodo privato fillBuffer().Vediamolo:
private void fillBuffer( float[] samples )
{
if( buffer.length < samples.length )
buffer = new short[samples.length];
for( int i = 0; i < samples.length; i++ )
buffer[i] = (short)(samples[i] * Short.MAX_VALUE);
}
Accoglie come parametro la matrice float[] che gli viene passata da writeSamples che lo invoca.Con le prime due righe...
if( buffer.length < samples.length )
buffer = new short[samples.length];
...se la grandezza del buffer è di dimensioni inferiori a quella del parametro che viene passato, crea una nuova matrice come buffer, di dimensioni uguali a quelle del parametro;
quindi per ogni elemento contenuto nella matrice samples si prende un elemento del buffer e gli si dà il valore, castato a short, del corrispondente elemento di samples moltiplicato per Short.MAX_VALUE.
Cosa significa questo Short.MAX_VALUE?
Viene moltiplicato un tipo float per Short.MAX_VALUE.
Vediamo se riesco a trovare qualche ispirazione cercando intorno alla conversione short -> float.
Per capire tutto questo forse devo ripassarmi bene come sono strutturati i numeri in virgola mobile.
Quando io moltiplico un float per uno short, lo short viene preventivamente convertito in float?
Se do a uno short un valore superiore al suo massimo, che valore assume la variabile?
Vediamo...
Mi devo costruire dei modelli.
Ecco, come ricordavo, la moltiplicazione di un float per uno short dà un risultato di tipo float.
float numeroFloat = 5.2f;
short numeroShort=2;
float risultato=numeroFloat * numeroShort;
System.out.println(risultato);
Ottengo come risultato:
11-14 17:06:10.752 4130-4130/? I/System.out: 10.4Se invece do al risultato il tipo short:
float numeroFloat = 5.2f;
short numeroShort=2;
short risultato=numeroFloat * numeroShort;
System.out.println(risultato);
...ottengo un errore, perché il risultato non può essere short ma è float.
Ora è il caso di ripassare a dovere i numeri in virgola mobile, perché credo che una risposta mi può venire solo da lì.
Iscriviti a:
Post (Atom)