Generador de letras de reggaetón

Disclaimer: this is completely unrelated to computer science or VOIP :D.

Este post es mi respuesta a @mharcos y @markosbenitez quienes me desafiaron a hacer un programa que genere letras de reggaetón a partir de unas instrucciones (abajo) posteadas en facebook.

Con un script hecho en PHP fui capaz de generar letras como esta:

Gata yo quiero azotarte fuerte hasta manhana
Chica yo quiero cogerte lento hasta manhana
Chica vamos a castigarte duro hasta manhana
Perra vamos a cogerte fuerte hasta que salga el sol

azotarte azotarte azotarte, toda la noche, suave … x3

Perra vamos a castigarte duro todo el dia
Perra yo voy a castigarte duro hasta manhana
Gata vamos a cogerte suave todo el dia
Chica yo quiero encenderte rapido hasta el amanecer

azotarte azotarte azotarte, toda la noche, lento … x3

Perra yo quiero darte suave hasta manhana
Mami yo vengo a azotarte lento hasta que salga el sol
Chica yo voy a encenderte suave hasta el amanecer
Chica vamos a castigarte lento hasta el amanecer

darte darte darte, hasta que salga el sol, suave … x3

Con éste enlace podés generar más letras aleatorias. Con cada recarga se genera una nueva.

Para los entendidos del tema, acá les dejo el script.


define(‘MAXIMO_ESTROFAS’, 3);
define(‘NL_MARKER’, “n”);

$bloque_1 = array(‘Mami’, ‘Gata’, ‘Perra’, ‘Zorra’, ‘Chica’);
$bloque_2 = array(‘yo quiero’, ‘vamos a’, ‘yo voy a’, ‘yo quiero’, ‘yo vengo a’);
$bloque_3 = array(‘castigarte’, ‘cogerte’, ‘encenderte’, ‘darte’, ‘azotarte’);
$bloque_4 = array(‘duro’, ‘rapido’, ‘lento’, ‘suave’, ‘fuerte’);

$bloque_5 = array(‘hasta que salga el sol’,
‘toda la noche’,
‘hasta el amanecer’,
‘hasta manhana’,
‘todo el dia’);

$bloque_6 = array(‘sin miedo’,
‘sin anestesia’,
‘en el piso’,
‘contra la pared’,
‘sin compromiso’);

function GenerarLetra()
$estrofa = array();
$letra = array();

for ($i = 0; $i < MAXIMO_ESTROFAS; $i++)
$estrofa = array();

for ($j = 0; $j < RENGLONES_POR_ESTROFA; $j++)
array_push($estrofa, GenerarRenglon());

array_push($letra, implode(NL_MARKER, $estrofa).NL_MARKER);
array_push($letra, “[CORO]”);
array_push($letra, GenerarCoro().” … x3″.NL_MARKER);

print implode(NL_MARKER, $letra);

print GenerarLetra().”n”;

function GenerarRenglon()
global $bloque_1, $bloque_2, $bloque_3, $bloque_4, $bloque_5, $bloque_6;

return “{$bloque_1[rand() % count($bloque_1)]} “.
“{$bloque_2[rand() % count($bloque_2)]} “.
“{$bloque_3[rand() % count($bloque_3)]} “.
“{$bloque_4[rand() % count($bloque_4)]} “.
“{$bloque_5[rand() % count($bloque_5)]}”;

function GenerarCoro()
global $bloque_3, $bloque_4, $bloque_5;

$verbo = $bloque_3[rand() % count($bloque_3)];

return “$verbo $verbo $verbo, {$bloque_5[rand() % count($bloque_5)]}, {$bloque_4[rand() % count($bloque_4)]}”;




Espero les sirva de algo xD

Huawei modem as an answering machine

Here is a summary of my effort trying to make chan_dongle to work:

… I couldn’t …

and I don’t even tried, I’d rather prefer to write my own channel, but why? When three semi-functional projects with the same device and the same technology fails in completing their objectives, there must be something wrong with the approach probably because doing it as an Asterisk channel adds unnecessary complexity.

The project

I spent 2 days reading docs about AT and after I gained some expertise I tested them using minicom with an E177 modem. Everything worked as it should except for the audio.

Consider this scenario.

1. modem connected to USB port.
2. minicom opening data port (/dev/ttyUSB0 in most cases).
3. an external phone for making calls.

Now the test was as follows:

1. I called to the modem using the external phone.
2. I answered the call from minicom.
3. I started reading the audio port (/dev/ttyUSB1).
4. I hung up the call.

The signaling was fine, the call handling was fine but no audio was received from /dev/ttyUSB1. I wasted precious time looking for an answer because I was asking the wrong question, I even recurred to but without luck.

I explored chan_dongle‘s source tree expecting to find some missing initialization sequence but it’s really complicated to follow the code execution path on a heavily multi-threaded application like Asterisk so I decided to use strace to attach it to Asterisk’s PID and sniff for write syscalls to get a clue of what the channel was doing. My guess certainly worked: I missed the AT^DDSETEX=<diag-port> after the call is connected so I repeated the test including this command right after the call was answered and suddenly an audio stream was flowing through the port.


strace -f asterisk 2>&1 | grep write | grep AT
[pid 14715] write(17, “ATr”, 3 <unfinished …>
[pid 14715] write(17, “ATZr”, 4) = 4
[pid 14715] write(17, “ATE0r”, 5) = 5
[pid 14715] write(17, “AT+CGMIr”, 8) = 8
[pid 14715] write(17, “AT+CGMMr”, 8) = 8
[pid 14715] write(17, “AT+CGMRr”, 8) = 8
[pid 14715] write(17, “AT+CMEE=0r”, 10) = 10
[pid 14715] write(17, “AT+CGSNr”, 8) = 8
[pid 14715] write(17, “AT+CIMIr”, 8) = 8
[pid 14715] write(17, “AT+CPIN?r”, 9) = 9
[pid 14715] write(17, “AT+COPS=0,0r”, 12) = 12
[pid 14715] write(17, “AT+CREG=2r”, 10 <unfinished …>
[pid 14715] write(17, “AT+CREG?r”, 9) = 9
[pid 14715] write(17, “AT+CNUMr”, 8) = 8
[pid 14715] write(17, “AT^CVOICE?r”, 11) = 11
[pid 14715] write(17, “AT+CSCA?r”, 9) = 9
[pid 14715] write(17, “AT+CSSN=1,1r”, 12) = 12
[pid 14715] write(17, “AT+CMGF=0r”, 10) = 10
[pid 14715] write(17, “AT+CSCS=”UCS2″r”, 15) = 15


Answering machine

I decided to write a program to try out what I learned these days and this project came to my mind. It might not be the best execution of an idea but hopefully will help me to master the techniques required to make and receive phone calls using Huawei modems in a minimalist scenario where debugging is not a reason to shoot yourself in the face.

The program connects to the modem and waits for an incoming call which when received, is picked up and a prerecorded sound file is played to the caller. It’s a pretty straightforward idea and involves 80% of what is necessary to implement an Asterisk channel that does the same in another context.

[bash]$ /answering_machine /dev/ttyUSB0 /dev/ttyUSB1 /home/carlos/rec.raw [/bash]

– The 1st parameter is the data port.
– The 2nd paramater is the audio port.
– The 3th paramater is an arbitrary signed 16bit PCM 8000 Hz file.

Having supplied those arguments, the program picks up any incoming call and plays the file pointed by the third parameter.

You can find the code here and for now, to compile it you have to import it as an Eclipse project because the Makefile is missing (for now).

Dinstar DWG2000 SMS API stable release

I’ve finished the first stable release of the DWG2000 messaging API. I tested it dozens of times and appears stable after 24 hours of constant running. I’m aware of the memory leaks but I’ll fix this issue as soon as I can.

The code is pretty straightforward and self explanatory. By now this is just for personal use but if any of you are working with the same family of products, I can definitely help you. It is not ready for production, but it works.

* main.c
* Created on: Mar 28, 2012
* Author: caruizdiaz

#include “util.h”
#include “dwg/dwg.h”
#include “networking/ip_socket.h”

void new_sms_handler(dwg_sms_received_t *sms)
LOG(L_DEBUG, “new sms from %s. Len: %d, Text: %sn”, sms->number, sms->message.len, sms->message.s);

void status_handler(dwg_ports_status_t *status)
int index = 0;

LOG(L_DEBUG, “tNumber of ports: %dn”, status->size);

for (index = 0; index < status->size; index++)
LOG(L_DEBUG, “tPort%d: %dn”, index, status->status_array[index].status);

void msg_response_handler(dwg_sms_response_t *response)
LOG(L_DEBUG, “tResponse from %sn”, response->number);

int main(int argc, char** argv)

dwg_message_callback_t callbacks = {
.status_callback = status_handler,
.msg_response_callback = msg_response_handler,
.msg_sms_recv_callback = new_sms_handler

dwg_start_server(7008, &callbacks);

str_t des = { “0981146623”, 10 };
str_t msg = { “hola”, 4 };

dwg_send_sms(&des, &msg);


Huawei modems with Asterisk, another frustration

There are many: chan_mobile, chan_datacard, chan_dongle. I tried them all but none of them actually “works”.  They failed in controlled lab environments, they worked for periods of time but ended crashing the module and Asterisk itself.

At the time of writing this post the frustration is eating me. I spent the weekend trying to make chan_dongle to work with an E177 modem which a friend of mine bought from Amazon two weeks ago.

Chan_dongle is an effort from a developer who decided to share his work with us, I’m not criticizing him, I’m just publishing the results of my lab test along with some of the frustration originated from it.

I’ll read the code, try to figure out what’s happening and If I succeed, I’ll publish the results here.


Opensource DWG2000 messaging API

In my spare time I do some consulting jobs mostly about telecom stuff and in one of these jobs I wrote a Dialer software for Asterisk which makes phone calls to users (numbers) loaded from a database. If the call is successful the program must inform the called party about what just happened by sending a SMS. Everything was OK until this feature was required.

We used a 8 ports DWG2000 GSM gateway manufactured by Dinstar which works really fine in terms of overall performance and voice quality. It also supports sending/receiving SMS’s but the API exposed works only on Windows machines and since the source code of the driver remains undisclosed, we (I’m part of a team) were unable to port it to Linux. What they do provide is a detailed protocol specification with enough documentation to implement it by myself and the result of that effort can be found in my github account.

It is still in a very early stage but I’m planning to implement the whole protocol soon but for now, it works for sending and receiving SMS’s, it suited quite well the requirements of my last consulting job.

What I’ve been doing these days

My initial goal when I started this blog was to write at least once a week about the things I did during the week but then I realize that the time I have is not enough or there’s something wrong with the way I set my schedule.

Anyway, the following is a list of the things I’ve been working on:

  1. International numbering plan.
  2. E.164 format specification.
  3. Routing/validation algorithm for E.164 numbers.
  4. Some Asterisk’s stuff.
  5. Openbravo ERP testing.
  6. Openbravo POS code modification to fit Paraguayan business rules.

Hopefully, there will be an independent post for every item on the list since writing a blog is an extraordinary way to document my work 😀


Script to upload users to Moodle

In my spare time, I am a maintainer of moodle powered platforms hosted by a company that offers e-learning services and this post is about uploading new students to that platform 😀

This task generally requires a CSV file filled with information about the student. The mandatory fields are username, first name, last name and email but this is just an example and some other fields may be required. The tutor or the course owner generally provides an excel file with the necessary data but since an username is needed to login and the students may not have an email account or is not a company’s policy to use personal email addresses for login, we have take alternative measures to fit the requirements.

Here are enumerated some rules imposed for standardization:

1. Username must be the first letter of the forename followed by the first surname, no spaces in between.
2. If no email account is provided, the system will provide one for the user, even if the account doesn’t exists yet.

This is how the file looks like:
1 Pedro Pedroso Cobranzas
2 Juan Perez Cobranzas
3 Juan Gonzalez Cobranzas
4 Un boludo No tiene Por ahi


And this is the output from the script:
username, password, firstname, lastname, email
ppedroso, elpassword*, Pedro, Pedroso,
jperez, elpassword*, Juan, Perez,
jgonzalez, elpassword*, Juan, Gonzalez,
uboludo, elpassword*, Un, boludo,

And finally, the script written in Perl. It explains itself very well I think, there is no need for line to line comment 😀

use strict;
use warnings;

open(FILE, “< $ARGV[0]"); print "username, password, firstname, lastname, emailn"; for ()
if ($_=~m/([a-z|A-Z]+)s([a-z|A-Z]+)/g)
my $name = $1;
my $lastname = $2;
my $username = lc(“$&$lastname”);
my $mail;

if (!($_=~m/[w|_|-]+@w+.(com|net)/g))
$mail = lc($name.$lastname).’’;
$mail = $&;

print “$username, elpassword*, $name, $lastname, $mailn”;
die ($_);

Existential crisis

Today I configured BIND from scratch and I realize that my knowledge on something as basic as DNS was a little too superficial. I tend to be perfectionist with the things related to my career but I will never master everything I like so I have to pick one of the many things in the list and try to make deep understanding on it.

What should I specialize in? I don’t know yet and I will delay the answer to avoid losing focus. In the meantime, I’ll keep posting and eventually the right answer will show itself, hopefully soon :D.

Date/Time operations

Since I am not very fanatic of software homogeneity, when I write perl scripts and I need some function that performs certain task I use commands from console whenever it’s available even knowing that could be an equivalent Perl module available out there.

When your main goal is to get things done in the least amount of time, you cannot afford the time wasted in searching a library/module when the tools are just as far as calling a external program. This doesn’t mean that your code has to look horrible, it means that there’s no need to search for a (long) piece of code to attach it to yours in order to make your program homogeneous. After all, if you know how to write clean code, you will do it even if you mix 2323423423 languages inside your perl script.

Date/Time arithmetic using Perl.

I am aware of the existence of but I have no experience using it. This was not the case with date command which finally led me to skip the learning curve and pass directly to the coding job.

The problem.

From a CDR entry containing end-datetime and duration, calculate the start-time, and transform the output using the YYMMDD/HHMMSS format.


use strict;
use warnings;

sub main()
my $startTime = “02/01/2011 12:02:00”;
my $secs = 3650;

print “$startTime – $secs secs (YYMMDD HHMMSS) = @{ [ CalculateDate(“$startTime”, $secs) ] }”;
print “$secs secs in HHMMSS format is = @{ [ FormatTime($secs) ] } n”;

sub CalculateDate($$)
my ($date, $secs) = @_;

$date = FormatDateTime(date --date "$date $secs seconds ago");

return $date;

sub FormatDateTime($)
return date --date "$_[0]" +"%y%m%d %H%M%S";

sub FormatTime($)
my ($seconds, $hours, $mins, $secs) = shift;

$hours = padLeft(int($seconds / 3600));

$mins = padLeft($hours == 0 ? int($seconds / 60) : int(($seconds – ($hours * 3600)) / 60));

$secs = padLeft($hours == 0 && $mins == 0 ? $seconds : $seconds % 60);

return “$hours$mins$secs”;

sub padLeft($)
my $value = shift;
return (length “$value” == 1) ? “0$value” : $value;


And the output is

$ perl
02/01/2011 12:02:00 – 3650 secs (YYMMDD HHMMSS) = 110201 110110
3650 secs in HHMMSS format is = 010050

Now, what I did not found searching the web was an easy method to convert seconds to a hour:minute:second format. This forced me to write my own algorithm which, hopefully, is bug free 😀
sub FormatTime($)
my ($seconds, $hours, $mins, $secs) = shift;

$hours = padLeft(int($seconds / 3600));
$mins = padLeft($hours == 0 ? int($seconds / 60) : int(($seconds – ($hours * 3600)) / 60));
$secs = padLeft($hours == 0 && $mins == 0 ? $seconds : $seconds % 60);
return “$hours$mins$secs”;

What would a portability freak say?

It would probably say that my solution ignores the portability features of Perl. Yes, it is true but I don’t really care since my target is, and will always be, Unix based machines.