Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Speex 1.2b - DTX like not working (Read 6005 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Speex 1.2b - DTX like not working

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: [Select]
// 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: [Select]
// 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: [Select]
// ~ 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