#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <DIRECT.H>

/*
//////////////////////////////////////////////////////////////////////////
PCM, DPCM, DM 과제
과제기간: 20141007 부터 기말고사 전까지 입니다.

wav 노래 파일 김동률의 '그게 나야(How I am)' 일부 입니다.

18초 정도의 오디오 wav 파일을 읽습니다.

프로그램은 wav 파일을 읽는 과정까지 구성되어 있습니다.
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
프로그램 제출 기한.

2014.10.07부터 기말고사 전까지 입니다.

프로그램은 메일등 파일 형태로 받지 않습니다.
작성한 프로그램은 표본화부터 문서를 출력해서 제출하면 됩니다.

10월 제출 12점
- 10월달은 함수를 이용해 프로그램을 구성해 보세요. (예. 표본화 함수, 양자화 함수, 부호화 함수, 복호화 함수)

11월 제출 10점

12월 제출 5점

미제출시 -5점
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
프로그램에서 PCM, DPCM, DM 파라미터(parameter)

송신기
1.  표본화 - wav 파일을 읽은 후 샘플링 주기는 3000 샘플 간격으로 표본화하여 PAM 신호를 구성합니다.
    표본화 샘플 개수는 95~96개 정도 입니다.

2.  양자화 - 선형 양자화로 구성합니다.
    사용자가 임의로 비트(bit)를 직접 정해서 프로그램을 작성하면 됩니다.
 
 PCM, DPCM 비트(bit)는 최소 2비트 이상
 DM는 1bit
 주의 DM을 구성할때는 step size를 잘 조절해야 할겁니다. 고정 step size 했을 때 샘플링 값과 양자화 오차가 있어도 약간은 비슷하면 됩니다.
 하지만 DM 된 신호의 파형 차이 심하면 DM 아닌 ADM으로 변경해서 프로그램 하세요.


3.  부호화 - n 비트로 구성된 비트 스트림(bit stream)으로 출력 하세요.

수신기
4.  복화화해서 양자화 된 PAM 신호값으로 복원
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
프로그램 구성
1. line 179 // 여기서 부터 프로그램을 작성하면 됩니다..
    프로그램 작성 부분부터 하면됩니다.

2.  프로그램 작성할때 아래 프로그램 처럼 할 필요없습니다.
 배열을 사용해 아는 부분을 최대로 작성해 주세요.

 양자화, 부호화 수식은 있어도 책에 있는 수식을 사용하면 프로그램이 복잡해지기 때문에
 간략화게 구성하면 됩니다.

3.  txt로 출력된 문서을 사용해 이론하고 비교해 제대로 되고 있는지 확인을 하세요.
 엑셀을 이용해 파형을 출력하면 됩니다. ( 표본화, 양자화, 복호화)
 콘솔(console)모드에서 검은색 잉크..너무 많이 사용하기 때문에 부호화 결과를 많이 부출력하지 마세요.  (부호화)

4 . 프로그램에서 작성시 주석은 필수 인거 아시죠?
 적절하게 필요한 부분만 어떤 역할을 하는지 정도 주석 넣어주세요.
 
5.  표본화, 양자화, 부호화, 복호화 프로그램
 파형- 표본화, 양자화, 복호화
 부호화는 데이터 값. 3비트인 경우. 000, 001, 010... 111로 출력하면됩니다.
///////////////////////////////////////////////////////////////
*/

#define Wav8bit        pow(2, (float) 8)    // 8bit max= 2^8 의미 없음.
#define SAMPLING_FREQUENCY   16000       // Sampling frequency
#define MAX_SIG_LENGTH     300000      // Maxmimun length of input - 10 s

#define SAMPLE_LIMIT      10000
#define InputSAMPLE       10000


void main()
{
 // 변수 선언
 char *filepath;
 FILE *wavload;
 
 
 // wave sample 변수
 int n;   
 int TempMAX;
 int TotalWavSamCount;
 
 
 //float *InSample;
 short *InFullData;   // wav input full sample data

 // PCM 변수
 int *SamplingData;   // Sampling Data

 // 현재 작업 폴더 위치에서 파일을 읽는다.
 char CurrentPath[_MAX_PATH];
 
 _getcwd(CurrentPath, _MAX_PATH);
 //printf("%s\n", CurrentPath);

 // filepath 초기화
 filepath= new char [_MAX_PATH];
 for(n=0; n<_MAX_PATH; n++)
  filepath[n]= NULL;
 
 printf("%s\n", filepath);

 //////////////////////////////////////////////////////////////////////////
 // wave 관련
 //////////////////////////////////////////////////////////////////////////
 // file read 확인
 

 if(wavload == NULL){
  printf("Error: Wav File load Error! \n");
  exit(1);
 }

 // wav data를 file로 저장한다.
 TotalWavSamCount= 0;
 fseek(wavload, 0L, SEEK_END);
 TotalWavSamCount= ( (ftell(wavload)-44)/2 );    // windows wav pcm header

 rewind(wavload);
 
 // cpp memory allocation
 InFull short [TotalWavSamCount];
 for(n=0; n<TotalWavSamCount; n++){
  InFullData[n]= 0;
 }

 fseek(wavload, 44L, SEEK_SET);
 fread((short *) InFullData, sizeof(short), TotalWavSamCount, wavload);
 // wavload close
 fclose(wavload);

 //////////////////////////////////////////////////////////////////////////
 // wav data를 txt file 문서로 저장. 폴더에서 확인해보세요.
 FILE *TxtPrint1;
 TxtPrint1=fopen("그게나야_out.txt", "w");
 for(n=0; n< TotalWavSamCount; n++)
  fprintf(TxtPrint1, "%d\n", InFullData[n] );
 fclose(TxtPrint1);
 //////////////////////////////////////////////////////////////////////////

 // 정규화(Normalization)
 // SampleData 최대값을 찾는다..
 TempMAX= 0;
 for(n=0; n< TotalWavSamCount; n++){
  if( TempMAX < abs(InFullData[n]))
   TempMAX= abs(InFullData[n]);
 }

 // SampleData 최대 크기값 -+256으로 변환
 for(n=0; n< TotalWavSamCount; n++)
  InFullData[n]= (InFullData[n]* Wav8bit)/ TempMAX ;


 //////////////////////////////////////////////////////////////////////////
 // wav data를 txt file 문서로 저장. 폴더에서 확인해보세요.
 FILE *TxtPrint2;
 TxtPrint2=fopen("샘플_out.txt", "w");
 for(n=0; n< TotalWavSamCount; n++)
  fprintf(TxtPrint2, "%d\n", InFullData[n] );
 fclose(TxtPrint2);
 //////////////////////////////////////////////////////////////////////////

 // wav end
 //////////////////////////////////////////////////////////////////////////


 //////////////////////////////////////////////////////////////////////////
 // 여기서 부터 프로그램을 작성하면 됩니다..
 // 표본화->양자화 -> 부호화 -> 수신기에서 복화화해서 양자화된 PAM 신호로 출력하면 됩니다.

 // 배열 및 변수 선언
 int PAM[95];        // 아날로그 신호 → PAM 신호
 int Sampling;        // 표본화

 int Discrete[95];   // 대표값
 int d;               // 레벨 간격

 char Coding[95][2]; // 부호화

 int Decoing[95];    // 복호화
 //////////////////////////////////////////////////////////////////////////
 // 1. 표본화(Sampling)
 //////////////////////////////////////////////////////////////////////////
 
 // 3000 샘플 간격으로 95개 표본화하여 PAM 신호를 구성
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  PAM[Sampling] = InFullData[Sampling * 3000];
 }

 // 표본화한 값을 텍스트 파일에 출력
 FILE *TxtPrint3;
 TxtPrint3=fopen("표본_out.txt", "w");
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  fprintf(TxtPrint3, "%d\n", PAM[Sampling]);
 }
 fclose(TxtPrint3);

 


 //////////////////////////////////////////////////////////////////////////
 // 2. 양자화(Quantization)
 //////////////////////////////////////////////////////////////////////////
  
 // 2비트일 때 레벨 간격 계산
 d=(2*256)/4;

 // 표본화한 값(PAM 신호값)을 각각의 대표값으로 변환     ※ 선형 양자화
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  if( PAM[Sampling] >= -256 && PAM[Sampling] < -256 + d )
  {
   Discrete[Sampling] = -192;
  }

  else if( PAM[Sampling] >= -256 + d && PAM[Sampling] < -256 + 2*d )
  {
   Discrete[Sampling] = -64;
  }
  
  else if( PAM[Sampling] >= -256 + 2*d && PAM[Sampling] < -256 + 3*d )
  {
   Discrete[Sampling] = 64;
  }

  else if( PAM[Sampling] >= -256 + 3*d && PAM[Sampling] < -256 + 4*d )
  {
   Discrete[Sampling] = 192;
  }
 }

 // 양자화한 값을 텍스트 파일에 출력
 FILE *TxtPrint4=fopen("양자_out.txt", "w");
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  fprintf(TxtPrint4, "%d\n", Discrete[Sampling]);
 }
 fclose(TxtPrint4);
  

 

 

 //////////////////////////////////////////////////////////////////////////
 // 3. 부호화(Coding)
 //////////////////////////////////////////////////////////////////////////

 // 대표값으로 양자화된 값을 2진 비트로 변환
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  if( Discrete[Sampling] == -192 )
  {
   Coding[Sampling][0] = 0, Coding[Sampling][1] = 0;
  }

  else if( Discrete[Sampling] == -64 )
  {
   Coding[Sampling][0] = 0, Coding[Sampling][1] = 1;
  }

  else if( Discrete[Sampling] == 64 )
  {
   Coding[Sampling][0] = 1, Coding[Sampling][1] = 0;
  }

  else if( Discrete[Sampling] == 192 )
  {
   Coding[Sampling][0] = 1, Coding[Sampling][1] = 1;
  }
 }

 // 부호화한 값을 텍스트 파일에 출력
 FILE *TxtPrint5;
 TxtPrint5=fopen("부호_out.txt", "w");
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  fprintf(TxtPrint5, "%d%d\n", Coding[Sampling][0], Coding[Sampling][1]);
 }
 fclose(TxtPrint5);
 

 

 

 //////////////////////////////////////////////////////////////////////////
 // 4. 복호화(Decoding)
 //////////////////////////////////////////////////////////////////////////

 // 2진 비트로 변환된 값을 다시 대표값으로 양자화된 값으로 복원
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  if( Coding[Sampling][0] == 0 && Coding[Sampling][1] == 0 )
  {
   Decoing[Sampling] = -192;
  }

  else if( Coding[Sampling][0] == 0 && Coding[Sampling][1] == 1 )
  {
   Decoing[Sampling] = -64;
  }

  else if( Coding[Sampling][0] == 1 && Coding[Sampling][1] == 0 )
  {
   Decoing[Sampling] = 64;
  }

  else if( Coding[Sampling][0] == 1 && Coding[Sampling][1] == 1 )
  {
   Decoing[Sampling] = 192;
  }
 }

 // 복호화한 값을 텍스트 파일에 출력
 FILE *TxtPrint6;
 TxtPrint6=fopen("복호_out.txt", "w");
 for( Sampling=0 ; Sampling<95 ; Sampling++ )
 {
  fprintf(TxtPrint6, "%d\n", Decoing[Sampling]);
 }
 fclose(TxtPrint6);


 

 

 //////////////////////////////////////////////////////////////////////////

 
 // 메모리 해제..
 delete InFullData;    
}

 

 

PCM이란걸로 한건데 계속 디버깅 실패하네.. 어디가 문제일까