Friday, April 28, 2017

Testing Opencore decoder

Once compiled, the test executable is in the folder /test/amrnb-dec
the program input is amr file and the output is wav file.


./amrnb-dec outamr8khz.amr outamr8khz.wav

Looking at the code, after decoding the stream, it needs to be converted to little endian for
wav format.

while (1) {
uint8_t buffer[500], littleendian[320], *ptr;
int size, i;
int16_t outbuffer[160];
/* Read the mode byte */
n = fread(buffer, 1, 1, in);
if (n <= 0)
break;
/* Find the packet size */
size = sizes[(buffer[0] >> 3) & 0x0f];
n = fread(buffer + 1, 1, size, in);
if (n != size)
break;

/* Decode the packet */
Decoder_Interface_Decode(amr, buffer, outbuffer, 0);

/* Convert to little endian and write to wav */
ptr = littleendian;
for (i = 0; i < 160; i++) {
*ptr++ = (outbuffer[i] >> 0) & 0xff;
*ptr++ = (outbuffer[i] >> 8) & 0xff;
}
wav_write_data(wav, littleendian, 320);
}

Opencore AMR - How to build and test and Verify encode and decode functionality

the build system is based on GNU. on the downloaded opencore-amr folder run the following two

./configure
make

output of ./configure
My-MacBook-Pro:opencore-amr retheeshravi$ ./configure 
checking for a BSD-compatible install... /usr/local/bin/ginstall -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/local/bin/gmkdir -p
checking for gawk... no
checking for mawk... no
checking for nawk... no
checking for awk... awk
checking whether make sets $(MAKE)... yes
checking how to create a ustar tar archive... gnutar
checking whether to enable maintainer-specific portions of Makefiles... no
checking build system type... i386-apple-darwin15.5.0
checking host system type... i386-apple-darwin15.5.0
checking for g++... g++
checking whether the C++ compiler works... yes
checking for C++ compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking for style of include used by make... GNU
checking dependency style of g++... gcc3
checking for gcc... gcc
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking whether ln -s works... yes

checking whether make sets $(MAKE)... (cached) yes


Output of make
Make will make the executables based on the output from configure script. 
my-MacBook-Pro:opencore-amr retheeshravi$ make
/Users/mymacbook/Downloads/Xcode.app/Contents/Developer/usr/bin/make  all-recursive
Making all in amrnb
make[2]: Nothing to be done for `all'.
Making all in amrwb
make[2]: Nothing to be done for `all'.
Making all in test
  CC     amrwb-dec.o
  CC     wavwriter.o
  CCLD   amrwb-dec
  CC     amrnb-dec.o
  CCLD   amrnb-dec
  CC     amrnb-enc.o
  CC     wavreader.o
  CCLD   amrnb-enc
  CC     linkboth.o
  CCLD   linkboth
  CC     amrnb-enc-sine.o
  CCLD   amrnb-enc-sine

Now we can run the amrnb-dec, amrnb-enc programs independantly and get the results. 

references:

Thursday, April 27, 2017

C Search and Replace

A sample C code to search and replace string in a text

void str_replace(char *target, const char *needle, const char *replacement)
{
    char buffer[1024] = { 0 };
    char *insert_point = &buffer[0];
    const char *tmp = target;
    size_t needle_len = strlen(needle);
    size_t repl_len = strlen(replacement);
    
    while (1) {
        const char *p = strstr(tmp, needle);
        
        // walked past last occurrence of needle; copy remaining part
        if (p == NULL) {
            strcpy(insert_point, tmp);
            break;
        }
        
        // copy part before needle
        memcpy(insert_point, tmp, p - tmp);
        insert_point += p - tmp;
        
        // copy replacement string
        memcpy(insert_point, replacement, repl_len);
        insert_point += repl_len;
        
        // adjust pointers, move on
        tmp = p + needle_len;
    }
    
    // write altered string back to target
    strcpy(target, buffer);

}

C++ how to get the absolute file path from iOS Cache directory

With code below I able to access cache folder in my app. I think, documents folder in "/Library/Documents", or somewhere else.

char *home = getenv("HOME");
char *subdir = "/Library/Caches/subdir";

char fullpath[200];
strcpy(fullpath,home);

strcat(fullpath, subdir);

Next, with full path, you can do usual things to read/write in C++

references:
http://stackoverflow.com/questions/13469342/using-c-to-access-documents-folder-on-ios

A collection of RTP tools

There are a few useful tools here.

rtpplay
tpplay reads RTP session data, recorded by rtpdump -F dump from either the file or stdin, if file is not specified, sending it to network address destination and port port with a time-to-live value of ttl.

If the flag -T is given, the timing between packets corresponds to the arrival timing rather than the RTP timestamps. Otherwise, for RTP data packets, the timing given by the RTP timestamps is used, smoothing interarrival jitter and restoring packet sequence. RTCP packets are still sent with their original timing. This may cause the relative order of RTP and RTCP packets to be changed.

The source port(localport) for outgoing packets can be set with the -s flag. A random port is chosen if this flag is not specified.

The whole file is played unless the begin or end times are specified. Times are measured in seconds and fractions from the beginning of the recording.

The RTP clock frequency is read from the profile file if given; the default profile (RFC 1890) is used if not. The profile file contains lines with two fields each: the first is the numeric payload type, the second the clock frequency. The values read from the profile file are silently ignored if the -T flag is used.

If you want to loop a particular file, it is easiest to put the rtpplay command in a shell script.

The -v flag has rtpplay display the packets generated on stdout.

rtpplay uses the hsearch (3C) library, which may not be available on all operating systems.

rtpdump

rtpdump [-F format] [-t duration] [-x bytes] [-f file] [-o outputfile] address/port
rtpdump listens on the address and port pair for RTP and RTCP packets and dumps a processed version to outputfile if specified or stdout otherwise.

If file is specified, the file is used instead of the network address. If no network address is given, file input is expected from stdin. The file must have been recorded using the rtpdump dump format.

The recording duration is measured in minutes.

From each packet, only the first bytes of the payload are dumped (only applicable for "dump" and "hex" formats).

rtpsend

rtpsend sends an RTP packet stream with configurable parameters. This is intended to test RTP features. The RTP or RTCP headers are read from a file, generated by hand, a test program or rtpdump (format "ascii").

rtpsend [-a] [-l] [-s sourceport] [-f file] destination/port[/ttl]

Packets are sent with a time-to-live value ttl.

If data is read from a file instead of stdin, the -l(loop) flag resends the same sequence of packets again and again.

The source port(localport) for outgoing packets can be set with the -s flag. A random port is chosen if this flag is not specified.

If the -a flag is specified, rtpsend includes a router alert IP option in RTCP packets. This is used by the YESSIR resource reservation protoccol.

The file file contains the description of the packets to be sent. Within the file, each entry starts with a time value, in seconds, relative to the beginning of the trace. The time value must appear at the beginning of a line, without white space. Within an RTP or RTCP packet description, parameters may appear in any order, without white space around the equal sign. Lines are continued with initial white space on the next line. Comment lines start with #. Strings are enclosed in quotation marks.

rtptrans

tptrans RTP/RTCP packets arriving from one of the addresses to all other addresses. Addresses can be a multicast or unicast. TTL values for unicast addresses are ignored. (Actually, doesn't check whether packets are RTP or not.)

Additionally, the translator can translate VAT packets into RTP packets. VAT control packets are translated into RTCP SDES packets with a CNAME and a NAME entry. However, this is only intended to be used in the following configuration: VAT packets arriving on a multicast connection are translated into RTP and sent over a unicast link. RTP packets are not (yet) translated into VAT packets and and all packets arriving on unicast links are not changed at all. Therefore, currently mainly the following topology is supported: multicast VAT -> translator -> unicast RTP; and on the way back it should lokk like this multicast VAT <- able="" agent="" and="" audio="" be="" both="" link="" means="" on="" p="" rtp.="" should="" that="" the="" this="" translator="" unicast="" use="" vat.="" vat="">
references:
http://www.cs.columbia.edu/irt/software/rtptools/

Tuesday, April 25, 2017

C commands to create Object file, executables

Below are some basic steps

 g++ -c my_lib.cpp => gives output as my_lib.o
 gcc -c my_lib.c => gives output as  my_lib.o

to link my_source.c with object my_lib.o file, below to be used.
gcc my_source.c my_lib.o

gcc 

Saturday, April 22, 2017

Extern Keyword in C

extern allows one module of your program to access a global variable or function declared in another module of your program. You usually have extern variables declared in header files. extern is used to let other C files or external components know this variable is already defined somewhere.

Using extern is only of relevance when the program you're building consists of multiple source files linked together, where some of the variables defined, for example, in source file file1.c need to be referenced in other source files, such as file2.c.

It is important to understand the difference between defining a variable and declaring a variable:

1) A variable is defined when the compiler allocates the storage for the variable.

2) A variable is declared when the compiler is informed that a variable exists (and this is its type); it does not allocate the storage for the variable at that point.

You may declare a variable multiple times (though once is sufficient); you may only define it once within a given scope.

Best way to declare and define global variables

Although there are other ways of doing it, the clean, reliable way to declare and define global variables is to use a header file file3.h to contain an extern declaration of the variable. The header is included by the one source file that defines the variable and by all the source files that reference the variable. For each program, one source file (and only one source file) defines the variable. Similarly, one header file (and only one header file) should declare the variable.

file3.h
extern int global_variable;  /* Declaration of the variable */

file1.c
#include "file3.h"  /* Declaration made available here */
#include "prog1.h"  /* Function declarations */

/* Variable defined here */
int global_variable = 37;    /* Definition checked against declaration */
int increment(void) { return global_variable++; }

file2.c
#include "file3.h"
#include "prog1.h"
#include

void use_it(void)
{
    printf("Global variable: %d\n", global_variable++);
}

prog1.h
extern void use_it(void);
extern int increment(void);

prog1.c
#include "file3.h"
#include "prog1.h"
#include

int main(void)
{
    use_it();
    global_variable += 19;
    use_it();
    printf("Increment: %d\n", increment());
    return 0;
}

references:
http://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files-in-c