Audio úlohy na signálovém procesoru DSK6455

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] Samostatná práce

[editovat] Zadání

Práce má za úkol demonstrovat ukázkové audio úlohy (vhodné například pro výuku) na signálovém procesoru DSP TMS320C6455 od Texas Instruments. Úlohy jsou zaměřeny na generování a potlačování ozvěny v reálném čase. Programovacím prostředím je Code Composer Studio v4, kde se využívá jazyka C.

[editovat] Signálový procesor

Hlavními prvky procesoru jsou:

  • procesor s frekvencí 1GHz
  • AIC 23 stereo kodek
  • 128 MB paměti DDR2
  • 4 LED diody s přepínači
Signálový procesor DSK6455

Schéma signálového procesoru:

Schéma signálového procesoru

[editovat] Audio přemostění

Vstupní signál (v tomto případě generovaný ze zvukové karty počítače) může být vzorkován frekvencemi 8 kHz, 16 kHz, 24 kHz, 32 kHz, 44 kHz, 48 kHz, 96 kHz. Pro řečový signál je dostačující zvolit vzorkovací kmitočet 8 kHz.

Tato část kódu je převzatá z předmětu A2M32VAD (Vývoj aplikací a DSP) z katedry telekomunikací.

// PRŮCHOD SIGNÁLU

#include <math.h>
#include <stdio.h>			// standard I/O needed for printf
#include "dsk6455.h"			// Vlozit funkce DSK6455
#include "dsk6455_CODEC.h"		// Vlozit funkce DSK6455 obsluhujici kodek AIC23

// Promenna pro nastaveni kodeku
DSK6455_CODEC_Config config = {
    0x0017, 					// 0 DSK6455_CODEC_LEFTINVOL  Left line input channel volume
    0x0017, 					// 1 DSK6455_CODEC_RIGHTINVOL Right line input channel volume
    0x00ff, 					// 2 DSK6455_CODEC_LEFTHPVOL  Left channel headphone volume
    0x00ff, 					// 3 DSK6455_CODEC_RIGHTHPVOL Right channel headphone volume
    0x0011, 					// 4 DSK6455_CODEC_ANAPATH    Analog audio path control
    0x0000, 					// 5 DSK6455_CODEC_DIGPATH    Digital audio path control
    0x0000, 					// 6 DSK6455_CODEC_POWERDOWN  Power down control
    0x0053, 					// 7 DSK6455_CODEC_DIGIF      Digital audio interface format
    DSK6455_CODEC_FREQ_8KHZ, 	                // 8 DSK6455_CODEC_SAMPLERATE Sample rate control
    0x0001  					// 9 DSK6455_CODEC_DIGACT     Digital interface activation
};
 
 Uint32 Vzorek, Vystup;

void main(void) {
	
	DSK6455_init(); // Nastavit komunikaci s DDR, CPLD apod.
	DSK6455_CODEC_openCodec(&config);			// Nainicializovat McBSP a kodek a spustit je 
	
	// Audio premosteni
	
	while (1){
	
		while (!DSK6455_CODEC_read32(&Vzorek));	// Pockej si na vzorek z kodeku, bere vzorky z pc		
		
			
		Levy = (Int16)   ((Vzorek) & 0xFFFF);
		Pravy = (Int16)  ((Vzorek>>16) & 0xFFFF);
		
		Vystup = ((( (Uint32)Levy )&0xFFFF)<<16) | (((Uint32)Pravy)&0xFFFF);

		while (!DSK6455_CODEC_write32(Vystup)); // Zapis nacteny vzorek zpet do kodek
		
	}
}

[editovat] Generování ozvěny

Podobně se vytvoří i ozvěna vícenásobná. Pro ukázku jsou k dispozici výstupy zobrazené na osciloskopu.

Jednoduchá ozvěna
Vícenásobná ozvěna
// VYTVOŘENÍ JEDNODUCHÉ OZVĚNY

#include <stdio.h>			// standard I/O needed for printf
#include "dsk6455.h"			// Vlozit funkce DSK6455
#include "dsk6455_CODEC.h"		// Vlozit funkce DSK6455 obsluhujici kodek AIC23

// Promenna pro nastaveni kodeku
DSK6455_CODEC_Config config = {
    0x0017, 					// 0 DSK6455_CODEC_LEFTINVOL  Left line input channel volume
    0x0017, 					// 1 DSK6455_CODEC_RIGHTINVOL Right line input channel volume
    0x00ff, 					// 2 DSK6455_CODEC_LEFTHPVOL  Left channel headphone volume
    0x00ff, 					// 3 DSK6455_CODEC_RIGHTHPVOL Right channel headphone volume
    0x0011, 					// 4 DSK6455_CODEC_ANAPATH    Analog audio path control
    0x0000, 					// 5 DSK6455_CODEC_DIGPATH    Digital audio path control
    0x0000, 					// 6 DSK6455_CODEC_POWERDOWN  Power down control
    0x0053, 					// 7 DSK6455_CODEC_DIGIF      Digital audio interface format
    DSK6455_CODEC_FREQ_48KHZ, 	                // 8 DSK6455_CODEC_SAMPLERATE Sample rate control
    0x0001  					// 9 DSK6455_CODEC_DIGACT     Digital interface activation
};

 Uint32 Vzorek;
 const int ZPOZDENI = 20000; // zpoždění ozvěny
 Uint32 buffer [20000];
 Int16 Levy, Pravy, Levy2, Pravy2;
 const float AMPL = 0.5;
 int i;

void main(void) {
	
	DSK6455_init(); // Nastavit komunikaci s DDR, CPLD apod.
	DSK6455_CODEC_openCodec(&config);			// Nainicializovat McBSP a kodek a spustit je 
	
	i=0;

	// Audio premosteni
	while(1){
		
		Levy = (Int16)   ((Vzorek) & 0xFFFF);
		Pravy = (Int16)  ((Vzorek>>16) & 0xFFFF);
		Levy2 = (Int16)   ((buffer[i]) & 0xFFFF);
		Pravy2 = (Int16)  ((buffer[i]>>16) & 0xFFFF);
				
		Levy = (((int)Levy) + ((int)Levy2)*AMPL);
		Pravy = (((int)Pravy) + ((int)Pravy2)*AMPL);
		
		//Ozvěnu lze ovládat stiskem prvního (č.0) pinu
		if(DSK6455_DIP_get(0)==1) {
			Vzorek = ((( (Uint32)Levy )&0xFFFF)<<16) | (((Uint32)Pravy)&0xFFFF);
		}
		
		while (!DSK6455_CODEC_write32(Vzorek)); // Zapis nacteny vzorek zpet do kodek
		
		while (!DSK6455_CODEC_read32(&Vzorek));	// Pockej si na vzorek z kodeku
		
		// TVORBA OZVĚNY
		buffer[i] = Vzorek; //velikost 'buffer' udává zpoždění
		i++;
		if (i >= ZPOZDENI) i=0; //pokud buffer zaplníme, vrátíme se na začátek a budeme zapisovat nové hodnoty
		
		}
}

[editovat] Potlačení ozvěny

Pro potlačení ozvěny je využitá korelace signálu a následné odečtení. Celý algoritmus pracuje v reálném čase (s určitým zpožděním).

Korelace v CCSv4
// VYRUŠENÍ OZVĚNY

#include <math.h>
#include <stdio.h>						// standard I/O needed for printf
#include "dsk6455.h"			// Vlozit funkce DSK6455
#include "dsk6455_CODEC.h"		// Vlozit funkce DSK6455 obsluhujici kodek AIC23

// Promenna pro nastaveni kodeku
DSK6455_CODEC_Config config = {
    0x0017, 					// 0 DSK6455_CODEC_LEFTINVOL  Left line input channel volume
    0x0017, 					// 1 DSK6455_CODEC_RIGHTINVOL Right line input channel volume
    0x00ff, 					// 2 DSK6455_CODEC_LEFTHPVOL  Left channel headphone volume
    0x00ff, 					// 3 DSK6455_CODEC_RIGHTHPVOL Right channel headphone volume
    0x0011, 					// 4 DSK6455_CODEC_ANAPATH    Analog audio path control
    0x0000, 					// 5 DSK6455_CODEC_DIGPATH    Digital audio path control
    0x0000, 					// 6 DSK6455_CODEC_POWERDOWN  Power down control
    0x0053, 					// 7 DSK6455_CODEC_DIGIF      Digital audio interface format
    DSK6455_CODEC_FREQ_8KHZ, 	                // 8 DSK6455_CODEC_SAMPLERATE Sample rate control
    0x0001  					// 9 DSK6455_CODEC_DIGACT     Digital interface activation
};

//#define BUFFERLENGTH 20000;

 Uint32 Vzorek, Vystup;
 Uint32 buffer[20000];
 Int16 Levy, Pravy, Levy2, Pravy2,bufferL[20000];
 int zpozdeni;
 int POM, POM_Z;
 const int BUFFERLENGTH = 20000;
 Uint32 i,j,k,l,rozh,hlp;
 int a,c;
 Int32 soucet;
 float max1,max2,b,d,odm_d,k1,k2,amplituda;
 float korekce = 0.12;
 Int16 xcorr[20000];
 int pozice1,pozice2;

void main(void) {
		a = 1;
		c = 1;
		i = 8000;
		l = 0;
		max1 = 0;
		max2 = 0;
		rozh = 0;
		POM = 0;
		POM_Z = 0;
		amplituda = 0;
		zpozdeni = 0;
	
	DSK6455_init(); // Nastavit komunikaci s DDR, CPLD apod.
	DSK6455_CODEC_openCodec(&config);			// Nainicializovat McBSP a kodek a spustit je 

	//-----------------------------------------------------------------------------------
	
	printf("*****NAČÍTÁNÍ VZORKŮ***** \n");		
	
	while(1){

		while (!DSK6455_CODEC_read32(&Vzorek));	// Pockej si na vzorek z kodeku, bere zvuk z pc	
			
		Levy = (Int16)   ((Vzorek) & 0xFFFF);
		Pravy = (Int16)  ((Vzorek>>16) & 0xFFFF);
		
		Vystup = ((( (Uint32)Levy )&0xFFFF)<<16) | (((Uint32)Pravy)&0xFFFF);
		
		bufferL[i] = Levy;
		i++;
		
		if (i >= BUFFERLENGTH){
		i=0;
		l++;
		}
		if (l==2) break;
		
		while (!DSK6455_CODEC_write32(Vystup)); // Zapis nacteny vzorek zpet do kodek a posli ven
	}
	
		
		printf("*****KORELACE - VÝPOČET PARAMETRŮ***** \n \n");
		
		//korelace		
		for (j=0;j<BUFFERLENGTH;j++) {
        soucet = 0;
        	for (k=0;k<BUFFERLENGTH-j;k++) {
        	soucet += bufferL[k]*bufferL[k+j];

			}
		//soucet/=65536;				   //normovani
        xcorr[j] = (Int16) (soucet/65536);

        }

        for (i = 0;i<100;i++){
			if (xcorr[i] > max1){
				max1 = xcorr[i];
				pozice1 = i;
			}
        }
        
		//printf("pozice: %d \n", pozice1);
		//printf("maximum 1: %f \n", max1);
		
		for (i = 500;i<8000;i++){
			if (xcorr[i] > max2){
				max2 = xcorr[i];
				pozice2 = i;
			}		
		}
		
		//printf("pozice: %d \n", pozice2);
		zpozdeni = pozice2;
		//printf("maximum 2: %f \n", max2);
		
		// kvadratická rovnice pro výpočet zpoždění a amplitudy
		b = - max1/max2;
		d = (b*b) - (4*a*c);
		odm_d = sqrt(d);
		
		k1 = (-b + odm_d)/2*a;
		k2 = (-b - odm_d)/2*a;
		
		if (k1 < k2){
		amplituda = k1;
		}
			else {
				amplituda = k2;
		}
		
		amplituda = amplituda + korekce; //korekce výpočtu
		hlp = 1;
		printf("PARAMETRY: \n \n");
		printf("_zpozdeni: %d \n", zpozdeni);
		printf("_amplituda: %f \n \n", amplituda);
		//printf("*****KONEC VÝPOČTU PARAMETRŮ*****");
	
	while(1) {

		while (!DSK6455_CODEC_read32(&Vzorek));	// Pockej si na vzorek z kodeku, bere vzorky z pc

			Levy = (Int16)   ((Vzorek) & 0xFFFF);
			Pravy = (Int16)  ((Vzorek>>16) & 0xFFFF);
			Levy2 = (Int16)   ((buffer[i - POM_Z + POM]) & 0xFFFF);
			Pravy2 = (Int16)  ((buffer[i - POM_Z + POM]) & 0xFFFF);
		
			Levy = ((int)(Levy) - (int)(Levy2)*amplituda);
			Pravy = ((int)(Pravy) - (int)(Pravy2)*amplituda);
	
			
		Vystup = ((( (Uint32)Levy )&0xFFFF)<<16) | (((Uint32)Pravy)&0xFFFF);
					
		buffer[i] = Vystup;
		i++;
		if (i >= BUFFERLENGTH){
			i = 0;
		}
		
		if (i >= zpozdeni) rozh = 1;
		if (rozh == 0){
			POM = 0;
			POM_Z = 0;
		}
			else{
				POM_Z = zpozdeni;
		}
		
		if (rozh == 1 && i >= zpozdeni) POM = 0;
		if (rozh == 1 && i < zpozdeni) POM = BUFFERLENGTH;
		
		while (!DSK6455_CODEC_write32(Vystup)); // Zapis nacteny vzorek zpet do kodek a posli ven

		}
}
Osobní nástroje