Implementacja korektora dźwięku

2008-08-21 , Papiewski Łukasz , Programowanie / Kodzenie

  • 1.Wstęp
  • 2.Algorytmy
  • 3.Środowisko programistyczne i interfejs
  • 4.Obsługa karty dźwiękowej
  • 5.Przetwarzanie sygnału
  • 6.Zakończenie
  • 7.Kod
Wstęp

W tym projekcie postanowię państwu przybliżyć zagadnienia związane z przetwarzaneim dźwięku z naciskiem na multiplatformowośc (Linux, BSD, Windows)

Komunikacja z kartą dzwiękową

Należy przyznać, ze smutkiem że jak na razie Windows ze swoją biblioteka DirectSound daleko wyprzedza Alse oraz inne opensourcowe rozwiązania. Przykładowa implementacja w C++ dla platformy win32:

Klasa WAW
/*
	Plik WAV.C
	Bibliteka WAV programu WAVELIZER
 Wykonuje podstawowe czynności wczytywania i zapisywania formatu WAV
 
	Copyright (C) 2010 Łukasz Papiewski
 
	Niniejszy program jest wolnym oprogramowaniem 
	- możesz go rozpowszechniać dalej i/lub modyfikować 
	na warunkach Powszechnej Licencji Publicznej GNU wydanej 
	przez Fundację Wolnego Oprogramowania, 
	według wersji 3 tej Licencji lub dowolnej z późniejszych wersji.
 
	Niniejszy program rozpowszechniany jest z nadzieją, 
	iż będzie on użyteczny - jednak BEZ ŻADNEJ GWARANCJI, 
	nawet domyślnej gwarancji PRZYDATNOŚCI HANDLOWEJ albo 
	PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. 
	Bliższe informacje na ten temat można uzyskać z 
	Powszechnej Licencji Publicznej GNU.
 
Kopia Powszechnej Licencji Publicznej GNU powinna zostać ci 
dostarczona razem z tym programem. 
Jeżeli nie została dostarczona, odwiedź <http://www.gnu.org/licenses/>
*/
#include "wav.h"
#include <math.h>
#include <string.h>
#include <fstream>
 
 
	// empty constructor
	CWav::CWav()
        {
		myPath = NULL;
 
        }
 
	// constructor takes a wav path
	CWav::CWav(char* tmpPath)
{
		myPath = new char[200];
		strcpy(myPath, tmpPath);
		myChunkID=new char[5];
		myType = new char[5];
		leftChannel=NULL;
		rightChannel=NULL;
		myData=NULL;
		for (int i=0; i<5; i++)
		{
		 myChunkID[i]=0;
		 myType[i]=0;
      }
		ifstream inFile( myPath, ios::in | ios::binary);
		inFile.seekg(0, ios::beg);
		inFile.read( (char*) myChunkID, 4);
      inFile.seekg(4, ios::beg);
		inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize
      inFile.seekg(8, ios::beg);
      inFile.read( (char*) myType, 4);
		inFile.seekg(16, ios::beg);
		inFile.read( (char*) &mySubChunk1Size, 4 ); 
		// read the SubChunk1Size//inFile.seekg(20, ios::beg);
		inFile.read( (char*) &myFormat, sizeof(short) ); 
		// read the file format.This should be 1 for PC
		// //inFile.seekg(22,ios::beg);
		inFile.read( (char*) &myChannels, sizeof(short) ); 
		// read the # of channels (1 or 2)//inFile.seekg(24, ios::beg);
		inFile.read( (char*) &mySampleRate, sizeof(int) ); 
		// read the samplerate//inFile.seekg(28, ios::beg);
		inFile.read( (char*) &myByteRate, sizeof(int) ); 
		// read the byterate//inFile.seekg(32, ios::beg);
		inFile.read( (char*) &myBlockAlign, sizeof(short) ); 
		// read the blockalign//inFile.seekg(34, ios::beg);
		inFile.read( (char*) &myBitsPerSample, sizeof(short) ); 
		// read the bitspersample
		inFile.seekg(40, ios::beg);
      inFile.read( (char*) &mySubChunk2Size, 4);
      inFile.seekg(40, ios::beg);
		inFile.read( (char*) &myDataSize, sizeof(int) ); 
		// read the size of the data
		// read the data chunk
		myData = new char[myDataSize];
		inFile.seekg(44, ios::beg);
		inFile.read((char*) myData, myDataSize);	
		inFile.close(); // close the input file
 
		int j;
		if (myChannels==2)
		{
			len=myDataSize/4;
			leftChannel= new short[len];
			rightChannel= new short[len];
			for(int i=0; i<len; i++)
			{
          	j=4*i;
	     		leftChannel[i]=( short)(myData[j+1]);
	     		j=j+2;
		  		rightChannel[i]=( short)(myData[j+1]);
      	}
		}
		else if (myChannels==1)
		{
				  len=myDataSize/2;
			leftChannel= new short[len]; 
			for(int i=0; i<len; i++)
			{
          	j=2*i;
	     		leftChannel[i]=( short)(myData[j+1]);
			}
			rightChannel=leftChannel;
		}
 
}
 
 
 
		CWav::~CWav()
		{
			fprintf(stderr,"Activating CWaw destructor!");
			if (myPath!=NULL)
			{
					  fprintf(stderr,"... deleting myPath");
			delete[] myPath;
			myPath=NULL;
			}
			if (myChunkID!=NULL)
			{
				fprintf(stderr,"... deleting myChunkID");
         	delete[] myChunkID;
				myChunkID=NULL;
			}
			if (myType!=NULL)
			{
				fprintf(stderr,"... deleting myType");
         	delete[] myType;
				myType=NULL;
			}
			if (myData!=NULL)
			{
				fprintf(stderr,"... deleting myData");
         	delete[] myData;
				myData=NULL;
			}
			if (leftChannel!=NULL)
			{
				fprintf(stderr,"... deleting leftChannel");
				delete[] leftChannel;
				leftChannel=NULL;
			}
			if (rightChannel!=NULL && myChannels==2){
					fprintf(stderr,"... deleting rightChannel..");
					delete[] rightChannel;
					rightChannel=NULL;
			}
			fprintf(stderr,"done!");
		}
 
      char*
		CWav::getPath()
		{
			return myPath;
		}
		char*
		CWav::getID()
      {
         return myChunkID;
      }
      char*
      CWav::getType()
      {
         return myType;
      }
 
 
      void
		CWav::setPath(char* newPath)
		{
			myPath = new char[200];
			strcpy(myPath, newPath);
		}
 
	// write out the wav file
	bool
	CWav::save(const char* dest)
	{
		fstream myFile (dest, ios::out | ios::binary);
 
		// write the wav file per the wav file format
		myFile.seekp (0, ios::beg);
		myFile.write ("RIFF", 4);
		myFile.write ((char*) &myChunkSize, 4);
		myFile.write ("WAVE", 4);
		myFile.write ("fmt ", 4);
		myFile.write ((char*) &mySubChunk1Size, 4);
		myFile.write ((char*) &myFormat, 2);
		myFile.write ((char*) &myChannels, 2);
		myFile.write ((char*) &mySampleRate, 4);
		myFile.write ((char*) &myByteRate, 4);
		myFile.write ((char*) &myBlockAlign, 2);
		myFile.write ((char*) &myBitsPerSample, 2);
		myFile.write ("data", 4);
		myFile.write ((char*) &myDataSize, 4);
		int j=0;
		for(int i=0; i<len; i++)
		{
         j=4*i;
	     (myData[j+1])=leftChannel[i];
	     j=j+2;
		  (myData[j+1])=rightChannel[i];
      }
		myFile.write (myData, myDataSize);
		myFile.close();
		return true;
	}
 
	// return a printable summary of the wav file
	char*
	CWav::getSummary()
	{
		char *summary = new char[250];
		sprintf(summary, " Format: %dn
							 Channels: %dn
							 SampleRate: %dn
							 ByteRate: %dn
							 BlockAlign: %dn
							 BitsPerSample: %dn
							 DataSize: %dn",
								 myFormat,
								 myChannels,
								 mySampleRate,
								 myByteRate,
								 myBlockAlign,
								 myBitsPerSample,
								 myDataSize);
		return summary;
	}

Cytaty

- Simplicity is the ultimate sophistication. - Leonardo da Vinci,
- Popularny człowiek wzbudza zawiść potężnych - Thufir Hawat o Leto Atrydzie (na Kaladanie),
- Szczęście następuje po smutku, a smutek po szczęściu; człowiek jest naprawdę wolny, gdy przestaje rozróżniać między smutkiem a szczęściem, między dobrem a złem - Aforyzmy buddyjskie.