Code: Select all
///////////////////////////////////////////////////////////////////////////////
// "speech" recognition
//
/**/ string version="1.07";
//
///////////////////////////////////////////////////////////////////////////////
// programming language: NXC for Mindstorms NXT
// author: HaWe 2011
///////////////////////////////////////////////////////////////////////////////
// speak, and watch the real-time oscillograph.
// as soon as the oscillograph appears you may press BtnCenter to store.
// choose the slot to store by <<BtnLeft or  >>BtnRight
// press BtnCenter again to store, or press BtnExit to delete the pattern
///////////////////////////////////////////////////////////////////////////////
// io functions
#define printf1( _x, _y, _format1, _value1) { \
  string sval1 = FormatNum(_format1, _value1); \
  TextOut(_x, _y, sval1); \
}
//*****************************************
char LCDline[]={56,48,40,32,24,16,8,0};
inline bool btnhit(){
   return ( ButtonPressed(BTN1, false) || ButtonPressed(BTN2, false)
         || ButtonPressed(BTN3, false) || ButtonPressed(BTN4, false));
}
inline int cin() {
  int result = -1;
    if (ButtonPressed(BTN1, false))
      result = BTN1;
    else if (ButtonPressed(BTN2, false))
      result = BTN2;
    else if (ButtonPressed(BTN3, false))
      result = BTN3;
    else if (ButtonPressed(BTN4, false))
      result = BTN4;
    return result;
}
///////////////////////////////////////////////////////////////////////////////
#define MinPause  80
#define dbOffset  30
#define RecLen   128
#define RecSlots  16
int  BGrndNoise=50, dbMax;
int  SoundRecord[RecLen];             // detection: 0...RecLen:
int  SoundPattern[RecSlots][RecLen];  // patterns
char key;
///////////////////////////////////////////////////////////////////////////////
// File I/O
///////////////////////////////////////////////////////////////////////////////
inline void SoundExport() { // Data Export format: number-strings, seperated by ";"
  string sFileName = "FILE_EXP.dat";
  unsigned int nFileSize = (RecLen*4); //3 byte for number (text) plus 1 (";") each
  byte fHandle;
  int IOresult, counter=0;
  int ibuf, i;
  string s;
 
  ClearScreen();
  TextOut( 0,48, "SpeechRecogn "+version);
  DeleteFile(sFileName);
  IOresult = CreateFile(sFileName, nFileSize, fHandle);
  if (IOresult == LDR_SUCCESS) {
    ClearScreen();
    for (i=0; i<RecLen; i++)   {
        counter+=1;
        ibuf= SoundRecord[i];
        printf1( 0, 32, "counter =%5d", counter);
        printf1( 0, 24, "loudness=%5d", ibuf);
        s=NumToStr(ibuf);
        s=s + ";" ;
        fputs(s, fHandle);
    }
    CloseFile(fHandle);
    printf1( 0,16, "%s", "! FILE STORED !");
  }
  else  {
    printf1( 0,16, "%s", "Error-Save-Error");
    Wait(1000);
  }
}
//*****************************************
void WordSave(byte slot, bool saveIt) {
  string s, sFileName;
 
  unsigned int nFileSize = (RecLen*4); // integer (2) + CR (1) + LF (1) bytes
  byte fHandle;
  int IOresult, counter=0;
  int ibuf, i;
  s=FormatNum("%04d", slot);
  sFileName=StrCat(s, ".wpt");
  ClearScreen();
  TextOut( 0,48, "SpeechRecogn "+version);
  DeleteFile(sFileName);
 
  if (saveIt==FALSE) return;
 
  IOresult = CreateFile(sFileName, nFileSize, fHandle);
  if (IOresult == LDR_SUCCESS) {
    ClearScreen();
    for (i=0; i<RecLen; i++)   {
        counter+=1;
        ibuf= SoundPattern[0][i];
        printf1( 0, 24, "counter =%5d", counter);
        printf1( 0, 16, "loudness=%5d", ibuf);
        WriteLn(fHandle, ibuf);
    }
    CloseFile(fHandle);
    printf1( 0,16, "%s", "! FILE STORED !");
  }
  else  {
    ClearScreen();
    printf1( 0,16, "%s", "Error-Save-Error");
    Wait(1000);
  }
}
//*****************************************
void LoadLanguageCenter() {
  string sFileName;
  unsigned int nFileSize;
  byte fHandle;
  int IOresult;
  int ibuf, i, j=0, slot;
  string s;
  ClearScreen();
  TextOut( 0,48, "SpeechRecogn "+version);
  ListFilesType SearchRec;
  SearchRec.Pattern = "*.wpt";
  SysListFiles(SearchRec);
  while (SearchRec.Result == NO_ERR && j < ArrayLen(SearchRec.FileList))
  {
    sFileName=SearchRec.FileList[j];
    TextOut(0, LCDline[0], sFileName);
    s=SubStr(sFileName, 0, 4);
    slot=StrToNum(s);
    printf1( 0, LCDline[1], "slot=%3d", slot);
    IOresult = OpenFileRead(sFileName, nFileSize, fHandle);
    if (IOresult == LDR_SUCCESS) {
      for (i=0; i<RecLen; i++)   {
        ReadLn (fHandle, ibuf);
        SoundPattern[slot][i]=ibuf;
        printf1( 0, LCDline[2], "counter =%5d", i);
        printf1( 0, LCDline[3], "loudness=%5d", ibuf);
      }
      CloseFile(fHandle);
      printf1( 0, LCDline[7], "FILE%3d RELOADED!", slot);
    }
    else {
      ClearScreen();
      printf1( 0, LCDline[7], "! ERROR ! FILE%3d", slot);
      Wait(1000);
    }
    ClearLine(LCDline[1]);
    ClearLine(LCDline[2]);
    ClearLine(LCDline[3]);
    j++;
  }
 
}
///////////////////////////////////////////////////////////////////////////////
task SoundCheck() {
  int t,       // timer counter
      p,       // pause counter
      i, j,    // index
      peak,    // for oscilligraph
      slot=1,  // slot for sound records
      j_best,  // slot which matchs best
      buf;
  long SoundLevel,
       sum[RecLen],
       sum_min,
       d2;
  string str;
  while(true) {
    str=".";
    SoundLevel=SensorValue(S2);
    printf1(0,LCDline[0], "%s", "BGrndNoise=");
    printf1(60,LCDline[0], "%4d", SoundLevel);
    Wait(4);
    ////////////////////////////////////////
    //  record if min sound level reached //
    ////////////////////////////////////////
    if (SoundLevel>(BGrndNoise + dbOffset)) {
      p=dbMax=0;
      t=1;
      key=-1;
      ClearScreen();
      ArrayInit (SoundRecord, 0, RecLen);
      while (t<RecLen-1) {
        SoundLevel=SensorValue(S2)-BGrndNoise;
        if (SoundLevel > dbMax) dbMax=SoundLevel;
        // if observe Pause then Rec_Stop
        p= (SoundLevel<dbOffset)? p+1 : 0;
        if (p==MinPause) break;
        if (t%2==0) {
          peak=SoundLevel;
          LineOut ((t+1)/2, 0, (t+1)/2, peak/8);
        }
        printf1(0, LCDline[0], "%s", "store: press BtnCtr" );
        //..........................
        if (btnhit() && key==-1) key=cin();
        //..........................
        //////////////////////////////////////////
        //   normalize to sound level steps     //
        //////////////////////////////////////////
       
        SoundRecord[t]=(SoundLevel*128)/dbMax;
        if (SoundLevel < BGrndNoise)
          SoundPattern[0][t]=0;
        else
          SoundPattern[0][t]=(8*SoundRecord[t])/8;
       
        Wait(7);
        t++;
        if(t%25==0) str+=".";
      }
      SoundRecord[0]=t;                  // store current recording duration
      printf1(0, LCDline[0], "%s", "store: press BtnCtr" );
      if (t<100) Wait(200);
      for (i=t; i<RecLen; i++) {
         SoundPattern[0][i]=0;           // fill slot pattern with "0"
      }
      SoundPattern[0][0]=SoundRecord[0]; // store current recording duration
      if (btnhit()) key=getchar();       // wait until Btn up
     
      // SoundExport();
      //////////////////////////////////////////
      //   allow sound record to be stored    //
      //////////////////////////////////////////
      ClearScreen();
      if ( key == BTNCENTER ) {
         key=-1;
         printf1(0, LCDline[1], "%s", "store in slot:");
         printf1(0, LCDline[7], "%s", "<<-1 OK/del +1>>");
         while (key!=BTNEXIT && key!=BTNCENTER) {
           printf1(0, LCDline[2], "%2d", slot);
           key=getchar();
           if (key==BTNLEFT) {
             if (slot>1) slot-;
             else
             if (slot==1) slot=RecSlots-1;
           }
           else
           if (key==BTNRIGHT) {
             if (slot<RecSlots-1) slot++;
             else
             if (slot==RecSlots-1) slot=1;
           }
           else
           if (key==BTNCENTER) {
             for (i=0; i<RecLen; i++) {
               SoundPattern[slot][i]=SoundPattern[0][i];
             }
             printf1(1, LCDline[2], "stored: Slot %2d", slot );
             WordSave(slot, TRUE);
             Wait(300);
           }
           else
           if (key==BTNEXIT) {
             for (i=0; i<RecLen; i++)  {
               SoundPattern[slot][i]=0;
             }
             printf1(1, LCDline[2], "deleted:Slot %2d", slot );
             WordSave(slot, FALSE);
             Wait(300);
           }
         } // while
         ClearScreen();
         key=-1;
      }
      else
      //////////////////////////////////////////
      //  compare and recognize sound record  //
      //////////////////////////////////////////
      {
        sum_min=LONG_MAX; j_best=INT_MAX;
        str=".";
        for (j=1; j<RecSlots; j++) {
          TextOut(0, LCDline[1], str);
          sum[j]=0;
          if (SoundPattern[j][0]>10) {
            for (i=1; i < RecLen; i++) {
              d2=(SoundPattern[0][i]-SoundPattern[j][i]);
              sum[j]=sum[j] + d2*d2;
            }
          }
          else {
            sum[j]=LONG_MAX;
          }
          buf=sum[j];
          if (sum[j]<sum_min) {
            sum_min=sum[j];
            j_best=j;
          }
          str+=".";
        } // for j
        ClearLine(LCDline[1]);
        if (j_best< INT_MAX)
          printf1(0, LCDline[1], "recogn=Pattern%2d", j_best );
      } // else compare
    }
  } // while true
} // SoundCheck
void init() {
  unsigned long sbuf;
  SetLongAbort(true);
  SetSensorType(S2, SENSOR_TYPE_SOUND_DBA);
  SetSensorMode(S2, SENSOR_MODE_RAW);
  for (int i=0; i<1000; i++) sbuf+=SensorValue(S2);
  BGrndNoise=sbuf/1000;
}
task main(){
  init();
  LoadLanguageCenter();
  StartTask(SoundCheck);
  while (true)  {
  }
}