Toni DTMF

« Older   Newer »
  Share  
view post Posted on 2/5/2018, 09:48
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Non so, non mi piace molto, penso si possa fare meglio, ma una soluzione potrebbe essere:

CODICE
#include <stdlib.h>
#include <stdio.h>
#define N 18

int elimina_rip(int rip[], int no_rip[])
{
       int i;
       int cont=0;
       int temp=rip[0];
       no_rip[cont]=temp;
       for (i=1; i<N; i++)
       {
               if (rip[i]!=temp)
               {
                       cont++;
                       no_rip[cont]=rip[i];
                       temp=rip[i];
               }
       }
       return cont+1;
}


int main(void)
{
       int rip[N]={5,5,5,5,5,6,6,6,6,6,6,6,5,5,5,2,2,2};
       int no_rip[N];
       int n,i;
       n=elimina_rip(rip, no_rip);
       puts ("array senza ripetizioni");
       for (i=0; i<n; i++)
               printf ("%d ",no_rip[i]);
       return 0;
}


Ma... non so come applicare il tutto al programma dei toni...ci sono un sacco di grane.
Una cosa non ho chiesto : sapete per caso se lo standard dtmf ha tempi ben precisi ? Nel senso, quanto dura un tono ?
Io ho misurato cicrca 130 ms. Potrebbe essere un dato utile

Edited by GILA75 - 2/5/2018, 12:57
 
Top
view post Posted on 2/5/2018, 12:18
Avatar

GWFstory

Group:
Administrator
Posts:
359
Location:
da qui...., quo, qua. Siete curiosi di saperlo, vero? No? Beh, tanto non ve l'avrei detto.

Status:


CITAZIONE
Una cosa non ho chiesto : sapete per caso se lo standard dtmf ha tempi ben precisi ? Nel senso, quanto dura un tono ?

Non mi risulta che ci siano specifiche per la durata. Sicuramente ci sarà una durata minima per ottenere il riconoscimento, ma non credo nulla di ufficiale. Per la durata massima invece sono praticamente sicuro che non ci siano limiti, dato che anni fa esistevano i generatori dtmf da appoggiare sulle cornette che mantenevano il tono fino a quando non si rilasciava il tasto.

Edited by Robo67 - 2/5/2018, 13:51
 
Top
view post Posted on 2/5/2018, 12:47
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Grazie.
Volevo affidarmi al tempo per aggirare i problemi.
Il volume si alza ?
Si, leggi e fai fft, poi salta a x campioni (che in definitiva e' uguale a dire tempo) piu' in la nel file.
Come capirai, questo mi lega a vincoli temporali di durata, e anche il sample rate deve essere noto...quello lo potrei leggere nel file al massimo e adattare i calcoli.
Spassionatamente, che dici, meglio mollare ???
 
Top
view post Posted on 2/5/2018, 13:28
Avatar

GWFstory

Group:
Administrator
Posts:
359
Location:
da qui...., quo, qua. Siete curiosi di saperlo, vero? No? Beh, tanto non ve l'avrei detto.

Status:


CITAZIONE
Spassionatamente, che dici, meglio mollare ???

Che ti devo dire...Io non ho le conoscenze delle librerie che stai usando........ non conosco la FFT in modo approfondito perchè c'ho avuto poco a che fare..... E' come se mi chiedessi se una razzo che usa propellente organico sia meglio di quello a propellente gassoso.
Risposta: non ne ho un'idea. :huh:

Certo è che non puoi ragionare sui tempi, ma mi sembra impossibile che la funzione della FFT che stai usando tu non ti permetta una scansione periodica di un segnale (sostanzialmente un aggiornamento di quanto già letto prima), oppure non permetta di implementarlo in qualche modo chiamando la funzione ciclicamente dopo avere azzerato l'array che contiene i risultati.

Quello che intendo è che mi va benissimo il concetto che la FFT perda i riferimenti temporali, ma sicuramente manca qualcosa al ragionamento, perchè non servirebbe a nulla una funzione che si "ricorda" di quello che ha campionato 3 giorni prima e tu, per azzerare/aggiornare la lettura, devi spegnere il PC, prenderlo a mazzate o venderlo al migliore offerente. ^_^
 
Top
view post Posted on 2/5/2018, 13:48
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Il modo di ricomporre con il tempo c'e' certo.
Nella libreria che sto usando, da una fft puoi tornare ai campioni.
Ma come hai detto tu manca qualcosa nel mio ragionamento.
E in piu' molte altre rogne.
Non credere che io sappia piu' di te sulka fft, l'ho solo accennata.
Vediamo, forse meglio se comincio con un solo tasto.
Grazie intanto
 
Top
view post Posted on 2/5/2018, 17:16
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Aggiornamento...
Il singolo tasto sono riuscito a leggerlo, e sembra andare bene, devo solo fare la tabella di conversione.
Per ora stampa le frequenze del tasto.
Con un tasto singolo ho aggirato il problema dei picchi....a modo mio :)
é un po' lunga da spiegare, appena ho tempo, posto.
Comunque anche solo un tasto, sono davvero contento, non ci avrei sperato.
Poi mentre ero a spasso col cane...mi è venuta un'idea..
e povero cane...è dovuto salire perchè DOVEVO provare :)
Metto insieme le idee e posto
 
Top
Elemento 38
view post Posted on 2/5/2018, 18:56




In realta' non hai nemmeno bisogno di creare un nuovo array, puoi usare quello iniziale e usare la variabile che ti dice quanti elementi sono validi:
CODE
harrym@harrym-mbp &#57520; ~/tgw &#57520; cat elimina_dup.py
myarray = [5,5,5,5,3,3,3,6,6,6,5,5,2,1,1]
print myarray
k = myarray[0] # valore corrente
i = 1 # indice array iniziale
j = 0 # indice array da ritornare

while i < len(myarray):
   if myarray[i] != k:
       myarray[j] = k
       j += 1
       k = myarray[i]
   i +=1

myarray[j] = k

print myarray
print 'Elementi validi: ', j+1
print myarray[:j+1]


harrym@harrym-mbp &#57520; ~/tgw &#57520; python elimina_dup.py
[5, 5, 5, 5, 3, 3, 3, 6, 6, 6, 5, 5, 2, 1, 1]
[5, 3, 6, 5, 2, 1, 3, 6, 6, 6, 5, 5, 2, 1, 1]
Elementi validi:  6
[5, 3, 6, 5, 2, 1]
 
Top
view post Posted on 2/5/2018, 19:09
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Si, l'ho fatto al volo, e non era il massimo. Appena posso guardo bene
 
Top
view post Posted on 3/5/2018, 11:12
Avatar

GWFstory

Group:
Administrator
Posts:
359
Location:
da qui...., quo, qua. Siete curiosi di saperlo, vero? No? Beh, tanto non ve l'avrei detto.

Status:


CITAZIONE
Poi mentre ero a spasso col cane...mi è venuta un'idea..
e povero cane...è dovuto salire perchè DOVEVO provare :)
Metto insieme le idee e posto

Attento Gila. Stai parlando di un cane, non di un tamagotchi.
Ricordati che non lo puoi alimentare infilandogli uno spinotto da qualche parte.......malizioni!!, pensavo in un orecchio, o cambiandogli le pile (che non si sa esattamente in quale alloggiamento siano).
Ricordati inoltre che se vuoi portarlo fuori non ti basta scrivere:

void main (void)
{
unsigned int var; cane; guinzaglio; giardino;

var=cane+guinzaglio;
giardino=var<<4;
}
,ma devi realmente portarlo in giro.
Non vedrei bene neppure l'idea di fargli fare un lungo viaggio spedendolo via mail.

:P
 
Top
view post Posted on 3/5/2018, 12:10
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


No, no certo. Era una battuta !! Ci facciamo dei bei giri, e non sopporto nemmeno io chi li tratta come oggetti

A dire il vero e' il cane che porta in giro me. Sceglie il giro lui, si ferma, poi va...ma e' bello cosi'.
Ho il pc che mi fa i capricci. Se riesco sta sera posto come ho fatto per codificare un tono singolo. Un po' artigianale, ma legge bene. Gia' qualcosa :)

Edited by GILA75 - 3/5/2018, 15:29
 
Top
Elemento 38
view post Posted on 3/5/2018, 18:36




Gila mi hai fatto venire voglia di provare questo progetto anche a me :)
Ho sempre voluto imparare qualche libreria di machine learning e questo potrebbe essere il progetto giusto ...
 
Top
view post Posted on 3/5/2018, 18:42
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Infatti, una strada alternativa sono le reti neurali, ci avevo pensato.
Se fatto bene, sarebbe ancora meglio.
Prova ! Intanto io provo il metodo classico.
In python poi avrai librerie di NN gia' fatte e performanti.
Io un programma di reti retropropagate in C l'ho scritto.
Fa schifo a livello di leggibilita' ma per cose base funziona.
Prova Ele!!!

EDIT

Spiego come ho fatto a riconoscere un tono singolo (che per ora è già un successo)
* registro un file con audacity e lo salvo come wav.
* le caratteristiche sono 44100 hz sample rate, mono, 16 bit non compressi.

Una volta fatto il file, lancio il programma in C che lo apre in modalità binaria.
Cero la mia finestra di FFT da 8192 punti.
eseguo la FFT.
Inizialmente non funzionava, era perchè io la facevo solo sui primi 8192 campioni del file, quando invece devo ispezionare
tutto il file:
finestra_FFT=finestra_FFT+prossima finestra.
In questo modo ho la somma di tutti i pesi dei bit del file, che "intrinsecamente" contengono le frequenze.
Tutta questa somma la do alla fft, che fa il tutto a dovere, e quindi mi estrae i due picchi:
es tono 5:

1336 hz e 770 hz

C'era un problema però: io vado a cercare il picco (numero) più alto che mi rappresenta i 1336 hz, es 12800.
Ok, l'ho trovato facilmente. Ora devo trovare il picco del 770, cioè il secondo massimo.
In prossimità del 12800 (1336 hz) avrò sicuramente il secondo massimo, perchè il picco tende (se pur stretto) a scendere gradualmente.
E quindi non va bene.
Io ho ragionato così:
Registro a 44100 hz con una fft di 8182 punti.
Quindi la mia risoluzione in hz è: (44100/2)/(8182/2)=5.38 hz
Quindi nel mio array fatto di 8192 punti ogni posizione ha un step di 5. 38 hz.
Posizione 100 ? 5.38*100=538 hz
in posizione 100 leggerò l'intensità della frequenza 538 hz.
Abbiamo queste frequenze da analizzare:
1209,1336,1477,1633 (alte)
697,770,852,941. (basse)
Ora per ovviare al problema cosa faccio:
Vado a cercare il picco massimo, che è facile da trovare.
Ok, lo trovo.
Ora io so che la frequenza minima delle alte è:1209 hz, quindi 1209/5.38=224
Quindi dalla posizione dell'array fft 224-->FFT[224] in poi ci sono solo frequenze alte.
Quindi da li in poi azzero.
Riparto dall'inizio e trovo la minore.
Nel cercare i 2 picchi, mi conservo l'indice dell'array non il numero.
Di fatto a me serve l'indice per poter risalire alla frequenza:

indice*5.38=frequenza.
Una volta ottenuto, li mando a comparare, tenendo presente delle tolleranze dei 5.38 hz
Il 5 è : 1336 e 770
Ma io dalla mia fft potrei avere 1340 e 765, quindi do dei campi es:
CODICE
if (((F_max>1325) && (F_max<1345)) && ((f_max>755) && (f_max<780))) //1336 770
               {puts("_5");return;}


Questo a grandi linee.
Per letture multiple...vediamo.
Intanto dovrei approfondire la FFT a livello teorico.
Qui una bozza del programma, non è il massimo, ma è davvero una prova:
CODICE
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <fftw3.h>
#define N 8192
#define SAMPLE_R 22050
#define DATI_W 44

void cerca_max(double FFT[]);
void codifica (double F_max, double f_max);

void codifica (double F_max, double f_max)
{
       if (((F_max>1200) && (F_max<1220)) && ((f_max>685) && (f_max<710))) //1209  697->1 (frequenze)
               {puts("_1");return;}

       if (((F_max>1325) && (F_max<1345)) && ((f_max>685) && (f_max<710))) //1336 697->2
               {puts("_2");return;}

       if (((F_max>1465) && (F_max<1485))&& ((f_max>685) && (f_max<710))) //1477 697->3
               {puts("_3");return;}

       if (((F_max>1200) && (F_max<1220)) && ((f_max>755) && (f_max<780))) //1209 770->4
               {puts("_4");return;}

       if (((F_max>1325) && (F_max<1345)) && ((f_max>755) && (f_max<780))) //1336 770->5
               {puts("_5");return;}

       if (((F_max>1465) && (F_max<1485)) && ((f_max>755) && (f_max<780))) //1477 770->6
               {puts("_6");return;}

       if (((F_max>1200) && (F_max<1220)) && ((f_max>840) && (f_max<865))) // 1209 852->7
               {puts("_7");return;}

       if (((F_max>1325) && (F_max<1345)) && ((f_max>840) && (f_max<865))) //1336 852->8
               {puts("_8");return;}

       if (((F_max>1465) && (F_max<1485)) && ((f_max>840) && (f_max<865))) //1477 852->9
               {puts("_9");return;}

       if (((F_max>1325) && (F_max<1345)) && ((f_max>930) && (f_max<955))) // 1336 941->0
               {puts("_0");return;}

       if (((F_max>1620) && (F_max<1645)) && ((f_max>685) && (f_max<710))) //1633 697->A
               {puts("_A");return;}

       if (((F_max>1620) && (F_max<1645)) && ((f_max>755) && (f_max<780))) //1633 770->B
               {puts("_B");return;}

       if (((F_max>1620) && (F_max<1645)) && ((f_max>840) && (f_max<865))) //1633 852->C
               {puts("_C");return;}

       if (((F_max>1620) && (F_max<1645)) && ((f_max>930)&& (f_max<955)))  //1633 941->D
               {puts("_D");return;}

       if (((F_max>1465) && (F_max<1485)) && ((f_max>930) && (f_max<955))) // 1477 941->#
               {puts("_#");return;}

       if (((F_max>1200) && (F_max<1220)) && ((f_max>930) && (f_max<955))) //1209 941->*
               {puts("_*");return;}
}



void cerca_max(double FFT[])
{
       double step=SAMPLE_R/(N/2.0); //5.383
       double F_max=0.0;
       double f_max=0.0;
       int index;
       int i;
       for (i=0; i<50; i++) // cancello primi dati
               FFT[i]=0.0;                // componente continua (???)
//*************************************
// cerco picco frequenza maggiore
       for (i=0; i<N/2; i++)
       {
               if (FFT[i]>F_max)
               {
                       F_max=FFT[i];
                       index=i;
               }
       }
       printf ("HZ =%f\n", index*step);
       F_max=index*step;
//************************************
       for (i=200; i<N/2; i++) // azzero picchi frequenze maggiori
               FFT[i]=0.0;
       
// cerco picchi frequenze minori
       for (i=0; i<N/2; i++)
       {
               if (FFT[i]>f_max)
               {
                       f_max=FFT[i];
                       index=i;
               }
       }
       printf ("hz =%f\n", index*step);
       f_max=index*step;
       codifica (F_max,f_max);
       
}
                       


int main(void) {
   fftw_complex in[N], out[N]; /* double [2] */
   fftw_plan p;
       double FFT[N/2];
   int i=0;  
   int ris=0;
   short int w;
   FILE *fd;
 
   /* apre il file in lettura */
   fd=fopen("d.wav", "rb");
   if( fd==NULL )
       {
               perror("");
               exit(1);
       }
   
       fseek(fd,DATI_W,SEEK_SET);// mi posiziono al byte 44. Nei files wav
                                     // il 44° byte è dove partono i dati
        /* ciclo di lettura */

/*********************************************************************/
/* converto i dati a 16 bits in dati numerici                        */
//*********************************************************************/
       for (;;)
       {
               ris=fread(&w, sizeof(short int), 1, fd);  
               if( ris==0 )
                       break;
               in[i%N][0]=in[i%N][0]+w;
               in[i%N][1]=0;  
               i++;  
       }
       fclose(fd);
   
       /* forward Fourier transform, save the result in 'out' */
       p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
       fftw_execute(p);
 
       for (i = 0; i < N/2; i++) //memorizzo solo metà vettore
       {
               FFT[i]=(sqrt(out[i][0]*out[i][0])+ (out[i][1]*out[i][1]));
       }
                       
       //printf ("%f\n", f);
       fftw_destroy_plan(p); //praticante una free()
       cerca_max (FFT);
          return 0;
}

su ubuntu per compilare:
CODICE
gcc -Wall -g  mio_file.c -o xx -lfftw3 -lm

Logicamente la fftw3 deve essere installata.

Edited by GILA75 - 3/5/2018, 21:15
 
Top
view post Posted on 4/5/2018, 15:57
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


EVVIVA!!!!

Sono riuscito a fare una lettura di più tasti.
Ho fatto un po' di prove e funziona bene (almeno sembra)
Il programma è un po' artigianale. Nel senso, mancandomi la teoria della fft, mi devo arrangiare con altri modi.
Un lavoro ben fatto sarebbe quello di capire il discorso del tempo come viene interpretato.
Io ho solo dei vincoli purtroppo: sample rate che deve essere noto, e durata fissa del tono.
Se siete interessati vi dico come ho fatto.
Sono contento, non sarebbe certo un software del mondo reale\lavorativo, ma come passa tempo può andare.
E salvo imprevisti legge bene!!!
 
Top
view post Posted on 4/5/2018, 21:03
Avatar

GWFstory

Group:
Administrator
Posts:
359
Location:
da qui...., quo, qua. Siete curiosi di saperlo, vero? No? Beh, tanto non ve l'avrei detto.

Status:


Bravo Gila. A questo punto, visto che hai gettato il sasso, non puoi nascondere la mano, quindi devi postare il tutto, altrimenti è un lavoro a metà.

Ora ti resta da aprire una discussione sulla versione hardware del decoder DTMF, così discutiamo un po' su come funziona il tutto (e magari facciamo pure un progetto funzionante).
 
Top
view post Posted on 4/5/2018, 21:08
Avatar

Rompiball

Group:
Appassionati
Posts:
2,612
Location:
briansa

Status:


Grazie !
Appena posso posto il programma, e se avete voglia spiego il ragionamento.
Sicuramente come ho detto un po' contorto rispetto a saper usare bene la fft.
Ma come sappiamo, sono argomenti complessi, che io non ho mai studiato
Mi dispiace aver ripiegato sun un limite fisso di tempo del tono..avrei voluto una cosa piu' flessibile, ma per ora...
Versione hardware seguo con interesse, anche se non so se ora come ora riuscirei a farlo.
Dai, domani posto
 
Top
102 replies since 29/4/2018, 08:38   907 views
  Share