POLYTECH CLERMONT-FERRAND Application Note Implementation of a SPEEX decoder on RX62N RENESAS microcontroller 22/01/2012 Author : Sébastien PINNETERRE Engineering student in electrical engineering /embedded systems
1
Table of Contents Preface... 4 Chapter 1: Introduction... 5 1.1 1.2 SPEEX s features... 5 Application example... 5 Chapter 2: pre-necessary... 6 2.1 2.2 2.3 Required hardware... 6 Required software... 6 Software installation... 6 Chapter 3: Implementation of a Speex decoder... 7 3.1 3.2 3.3 3.4 3.5 Get back Speex codec source code... 7 Project creation... 7 Setup the KPIT GNURX tool chain... 7 Project organization... 8 Modification of source code... 9 2
Illustration table Figure 1: Quality versus bit-rate... 5 Figure 2: Example of application... 5 Figure 3 : KPIT GNURX Configuration... 7 Figure 4: library configuration... 8 Figure 5: library configuration... 8 Figure 6: Section configuration... 8 Figure 7: List of Speex files... 9 3
Preface This document provides all the necessary elements to implement a SPEEX decoder on RX62N RENESAS microcontroller on its RSK2+RX62N development board. 4
Chapter 1: Introduction 1.1 SPEEX s features The Speex codec is an open source speech codec. Speex is designed for packet networks and voice over IP (VoIP) applications. The Speex codec is designed to be very flexible and support a wide range of speech quality and bit-rate. Support for very good quality speech also means that Speex can encode wideband speech (16 khz sampling rate) in addition to narrowband speech (telephone quality, 8 khz sampling rate). The table below shows the quality versus the bit-rate in narrowband mode. Figure : Quality versus bit-rate 1.2 Application example Computer Speex file (.spx) Communication network Speex decoder Figure : Example of application This example shows an use of the Speex codec. The Speex file corresponding to a speech which has been recorded and encoded in Speex file before. This Speex file, stored on a computer is sent though a communication network to a Speex decoder which restores the speech to a speaker. 5
Chapter 2: pre-necessary This chapter deals with the necessary hardware and software to implement the Speex decoder. 2.1 Required hardware The following hardware has to be used: RSK2+RX62N development board RENESAS Debugger E1 2.2 Required software In order to implement the Speex decoder, following software have to be used: High-performance Embedded Workshop (HEW) HEW is a RENESAS integrated development environment which permits to do debugging. The used version for demonstrations will be the 4.09.00.007 version. - Downloadable at this link : http://www.renesas.com/support/downloads/jq_download_category/ide/hewv4090 0u_full_update.exe GNURX GNURX is a free compiler which is integrated at HEW. The used version for demonstrations will be the 11.03 version. - Downloadable at this link : http://www.kpitgnutools.com/latesttoolchain.php 2.3 Software installation It is necessary to respect an order of installation between HEW and GNURX. In first, HEW has to been installed. Once the installation is completed, GNURX may be installed. The GNURX tool chain will be automatically integrated in HEW. 6
Chapter 3: Implementation of a Speex decoder In this chapter, the procedure to implement the Speex decoder on RX62N microcontroller is enounced. Will be enounced, where find source code, how to create a new project to implement the Speex decoder, how the HEW software has to be configured etc 3.1 Get back Speex codec source code The first step consists in getting back Speex code source code on the official site web at this link: http://www.speex.org/. On the download section, several versions of the Speex codec can be found. The lasted version in date is the 1.2rc1 version which is also the recommended version. Download the speex-1.2rc1.tar.gz packet. It s also necessary to get back the ogg library which is not provided with Speex codec source code. This ogg library may be downloaded on the official site web at this link: http://www.xiph.org. On the download section, download the libogg-1.3.0.zip packet which contains the ogg library. 3.2 Project creation Create a new project and choose the GNURX tool chain. It s also necessary to setup the data endian in little endian data and use following header files: ctype.h; math.h; stdio.h; stdlib.h; string.h. 3.3 Setup the KPIT GNURX tool chain This part explains how to setup the GNU compiler. First, once the project was created, click on KPIT GNURX in the Build menu in order to open the setup compiler s window and follow these instructions: Select debug configuration In the link/library tab, select input category then show entries for C/C++ library as the illustration below : Figure : KPIT GNURX Configuration 7
Next, add these two following libraries at the list: rx-elf\rx-elf\optlibinc and rx-elf\bin\newlib\libc\common relative to tool chain install directory. See the illustration below : Figure : library configuration Figure : library configuration In the link/library tab, select section category, then configure section as following : Figure : Section configuration Valid configuration when it s finished 3.4 Project organization In this part is enounced what files are necessary to the project. For implementation of the decoder, source file of Speex codec downloaded are required plus ogg library files. From the speex- 1.2rc1.tar.gz packet, use the files from the folder include,libspeex and src. From the libogg-1.3.0.zip packet, use the files from the include/ogg. 8
The list of necessary files is listed below: -Speex sources: Figure : List of Speex files -Ogg library sources: ogg.h ; os_types.h 3.5 Modification of source code In this part is explained the main changes of source code to implement the speex decoder on the RX62N. os_types.h file This header file defines types for ogg format, they are defined depending on different systems which may exist. However these systems do not correspond to the RX62N, so lines which define type ogg_int16_t, ogg_uint16_t, ogg_int32_t, ogg_uint32_t, ogg_int64_t may be deleted and replaced by these lines below: typedef signed short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef signed int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef signed long long ogg_int64_t; typedef unsigned long long ogg_uint64_t; 9
speex_types.h file : This file defines types for Speex codec, as previously they are defined depending on different systems which may exist. So lines which define spx_int16_t, spx_uint16_t, spx_int32_t et spx_uint32_t type may be deleted and replaced by these lines below: typedef short spx_int16_t; typedef unsigned short spx_uint16_t; typedef int spx_int32_t; typedef unsigned int spx_uint32_t; Source codes are designed for operating systems which have graphic interface and used unnecessary functions for the application because they are not supported. Among these functions, there are printf and fprintf which may be deleted or commented. Decoding function : The main decoding function is located in speexdec.c file and corresponding to the main function. By default, it has int main(int argc, char **argv) as prototype. Indeed, the source code is designed for being used as a program that explains the use of argc and argv. These arguments are used to setup names of input and output files, and also to setup some options. To implement this decoding function to the RX62N, this function can be defined as a function without argument (void). For example: int speexdec(void) Now, there are different important points on which we have to work. The Speex decoder can be simplify as below: Start Reading option Opening input file Initialization of the decoder End Decoding loop Reading ogg packet from input file Decoding ogg packet loop Decoding speex packet Opening output file at first time Writing data in output file End of decoding ogg packet loop End of decoding loop Destruction of the decoder Closing files 10
To implement the decoder, follow instructions below: 1) Files don t have to be used and may be replaced by buffers. So file pointer, all function concerning the opening and the closing of files can be deleted. 2) The functions which managed options can be deleted because the options will be frozen. 3) The functions which managed Wave header can be deleted because we don t need to use Wave output file. 4) The fread function which is used to read the input file has to be replaced. Below, the prototype of this function: size_t fread (void *ptr, size_t size, size_t nmemb, FILE *stream); The fread function read nmemb elements of data of size octets of length, from the stream pointed by stream, and store its in location pointed by ptr. fread return the number of correct read elements. Below, the original code of the reading operation: while (1) { char *data; int i, j, nb_read; /*Get the ogg buffer for writing*/ data = ogg_sync_buffer(&oy, 200); /*Read bitstream from input file*/ nb_read = fread(data, sizeof(char), 200, fin); ogg_sync_wrote(&oy, nb_read); /*Loop for all complete pages we got (most likely only one)*/ while (ogg_sync_pageout(&oy, &og)==1) { Code details: Mainly the ogg_sync_buffer() function reserves a new memory area of 200 Bytes in a structure named oy and it returns the address of this memory area. The fread function permits to copy, by packet of 200 Bytes, data from the input file in the memory area of the oy structure pointed by data. nb_read saves the number of data read. 11
Mainly, the ogg_sync_wrote() function synchronizes data read depending on nb_read. Then, if read data from an ogg packet, so we enter in the decoding loop of ogg packet. The fread function can be replaced by the code below: memcpy(data, &buffer_in[cpt_buf_in], sizeof(char)*nb_read) ; cpt_buf_in = (cpt_buf_in + nb_read) % BUFFER_IN_SIZE; The memcpy function permits to copy memory areas. Here, nb_read is equal to 200 and permits to copy blocs of 200 Bytes from an input buffer named buffer_in to the memory area pointed by data. 5) The fwrite function which is used to write in the output file has to be replaced. Below, the prototype of this function: size_t fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream); The fwrite function writes nmemb elements of data of size octets of length, into the stream pointed by stream, from the location pointed by ptr. The fwrite function returns the number of correct written elements. Below, the original code of the writing operation: fwrite(out+frame_offset*channels, sizeof(short), new_frame_size*channels, fout); Code details: - out corresponding to the output buffer of a Speex decoded packet - channel corresponding to the number of channel (mono / stereo) - new_frame_size corresponding to the size of the data frame for one Speex packet (160 by default) The fwrite function can be replaced by the code below: for (i=0;i<frame_size*channels;i++) { } buffer_out_1[i]=( output[i+frame_offset] + 0x7fff) >> 6 ; We copy elements per elements data from output Speex decoding buffer to the buffer_out_1 buffer. Then these data can be converted by an analogic to digital converter (ADC). 12