IPB

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
Speex 1.2b - DTX like not working
alexscorpion
post Jul 31 2007, 12:54
Post #1





Group: Members
Posts: 1
Joined: 31-July 07
Member No.: 45760



hi there, i am writing voice chat and speex is in the root of it. i write it in Java and use JNI to link with 'C'-based Speex 1.2beta. [I know of JSpeex but there are not implemented some features]
recently i decided to use DTX feature of speex as well. the code follows. The problem is that no matter whether the data passed to the encoder is voice or not it always returns 1, meaning the encoded data should be send.
i test it this way: pass 2 frames of 20ms with zeros to the encoder, pass 2 frames with rand numbers[white noise as far as i know] and finally use file with voice and silence mixed.
all cases it returns 1.

please look at the code and point me something i miss or mistake:

CODE
// SpeexEncoder.cpp

#include "SpeexEncoder.h"

#include <stdlib.h>
#include <stdio.h>
#include <windows.h>

//
//   ======== Constructor ========
//
//  FUNCTION: initializes encoder with narrow or wide band
//            according to sampling frequency
//
//  PARAMETERS:
//             - fs - sampling frequency sets the speex mode nb/wb
//             - qlty - 1 to 10
//             - vad - 1 or 0, inicating on or off for the voice activity detection feature
//             - denoise - 1 or 0, inicating on or off for the denoising feature
//             - agc - 1 or 0, inicating on or off for the auto Gain control feature
//             - dtx- 1 or 0, inicating on or off for the discontinious transmition feature
//
//  RETURN VALUE: none
//
SpeexEncoder :: SpeexEncoder(int fs, int qlty, int vad, int denoise, int agc, int dtx)
{
    speex_bits_init(&bits);
     if(fs == 8000)
      {
       enc_state = speex_encoder_init(&speex_nb_mode);
      }
     else if(fs == 16000)
      {
       enc_state = speex_encoder_init(&speex_wb_mode);
      }
     else
      {
       MessageBox(NULL, "bad sampling frequency!", "SpeexEncoder", MB_OK | MB_ICONERROR);
      }
      
    int enc_frame;
    
    speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &enc_frame);
    
    frame_size = enc_frame;
    
    // Set the quality
    speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &qlty);
    // Set DTX
    speex_encoder_ctl(enc_state, SPEEX_SET_DTX, &dtx);
    //load lookahead
    speex_encoder_ctl(enc_state, SPEEX_GET_LOOKAHEAD, &lookahead);
    
    if (denoise || agc || vad)
    {
     preprocess = speex_preprocess_state_init(frame_size, fs);
     // Set VAD
     speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_VAD, &vad);          
     speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DENOISE, &denoise);
     speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC, &agc);
     lookahead += frame_size;
    }
    
};
//eof Constructor()========================================================



//
//   ======== Destructor ========
//
//  FUNCTION: destroys speex coder and decoder
//
SpeexEncoder :: ~SpeexEncoder()
{
speex_bits_destroy(&bits);
speex_encoder_destroy(enc_state);
speex_preprocess_state_destroy (preprocess);
};
//eof destructor()=========================================================



//
//   ======== Encode ========
//
//  FUNCTION: cycles through passed samples and codes each frame
//
//  PARAMETERS:
//             -  -
//             -  -
//
//  RETURN VALUE: 0 if frame needs not be transmitted (DTX only), 1 otherwise
//
//  NOTE : output must be huge enough to store the data!
//
int SpeexEncoder :: Encode(short* samples, int sampLen, char* output, int* written)
{

     if(sampLen != frame_size)
      {
       *written = 0;
       MessageBox(NULL, "sampLen must be equal to frame size", "Encode()", MB_OK | MB_ICONERROR);
       return 0; // error
      }
    
    char buffer[500];
    int nbBytes;
    
    speex_bits_reset(&bits);
    
    if (preprocess)
         speex_preprocess(preprocess, samples, NULL);

    // encode the frame  moving in the samples buffer
    int transmit = speex_encode_int(enc_state, samples, &bits);
    
    nbBytes = speex_bits_write(&bits, buffer, 500);
    
    //IntToFourChar(nbBytes, &output[*written]);
    CopyMemory( output, buffer, nbBytes);
    
    *written = nbBytes;
          
    return transmit;
};
//eof Encode()=======================================================


CODE
// Tester.cpp

#include "SpeexDecoder.h"
#include "SpeexEncoder.h"
#include "lpc_win.h"
#include <windows.h>
#include <stdio.h>

const int SAMPLES_LEN = 160;
const int CODED_DATA_LEN = 20;

const int FREQ = 8000;
const int QLTY = 4;
const int VAD = 1;
const int DENIOSE = 1;
const int AGC = 1;
const int ENH = 1;
const int DTX = 1;

int main ()
{
    SpeexEncoder* coder;
    
    decoder = new SpeexDecoder(FREQ, ENH);
    coder = new SpeexEncoder(FREQ, QLTY, VAD, DENIOSE, AGC, DTX);
    
    char fileName[] = "D:\\Speex\\myTestFiles\\test.raw";
    
    FILE *fin = fopen(fileName, "rb");
    if (!fin)
      {
         perror(fileName);
         exit(1);
      }
    
    short samples[SAMPLES_LEN] = {0};
    char output[CODED_DATA_LEN] = {0};
    
    int ret = 0;
    int written = 0;
    
    while (true)
    {
           ret = fread(samples, sizeof(short), SAMPLES_LEN, fin);
           if(ret != SAMPLES_LEN) break;
          
           ret = coder->Encode( samples, SAMPLES_LEN, output, &written);
          
            for (int a = 0; a < SAMPLES_LEN; a++)
              {
                  printf("%d ", samples[a]);
              }//for a
              printf(">>>>>");
          
           printf(" t = %d \n\n", ret);
          
    }
    
    delete coder;
    fclose(fin);
}


using speexenc.exe with the same file, works fine. I added printing and some parts of the file returns zero after encoding when dtx and vad are enabled.

CODE
// ~ line 830 in speexenc.c

if (preprocess)
         speex_preprocess(preprocess, input, NULL);

      transmit = speex_encode_int(st, input, &bits);
      for (a = 0; a < frame_size; a++)
      {
          fprintf(stderr,"%d ", input[a]);
      }//for a
      fprintf(stderr,">>>>>");
      
      if(transmit == 0)
      {
       fprintf(stderr," t = 0 |\n\n");
      }
      else
      {
       fprintf(stderr," t = 1 |\n\n");
      }


i think thats all

[edit] add speex_preprocess(preprocess, samples, NULL); before each call to speex_encode_int();
this doesn't solve the problem after all
[edit] removed Java code, only c++ because problem is there

This post has been edited by alexscorpion: Aug 24 2007, 12:34
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



RSS Lo-Fi Version Time is now: 16th April 2014 - 09:40