[Speex-dev] speex DTX chore

Project Maker new_project at abv.bg
Fri Aug 24 05:17:33 PDT 2007


hi there,
I am new to mailing list so excuse me if I don't obey to the 'netiquette'.
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]

[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);
}

[/code]

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");
	  }

[/code]

i think thats all

-----------------------------------------------------------------
ЕЛА и направи свой сайт, намери нови приятели!
http://www.zoom.bg/


More information about the Speex-dev mailing list