urbisound.cc

00001 /****************************************************************************
00002  * $Id: urbisound.cpp,v 1.9 2005/09/21 06:45:36 nottale Exp $
00003  *
00004  * Sample demonstration of URBI sound capabilities.
00005  *
00006  * Copyright (C) 2004, 2006, 2007 Jean-Christophe Baillie.  All rights reserved.
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00021 **********************************************************************/
00022 
00023 /* This simple demonstration program save to a file or send to the
00024  * speakers sounds coming from an Urbi server.  The data written is
00025  * the raw data as sent by the server (ers7 = 16000Hz stereo 16bit).
00026  * You can use the sox program to convert it.
00027  */
00028 
00029 #include "libport/cstdio"
00030 #include <ctime>
00031 #include <sys/types.h>
00032 #include "libport/sys/stat.h"
00033 
00034 #include <fcntl.h>
00035 #include "urbi/uclient.hh"
00036 
00037 #ifndef WIN32
00038 # include <sys/ioctl.h>
00039 # include <sys/soundcard.h>
00040 static const char *device="/dev/dsp";
00041 #endif
00042 
00043 struct wavheader
00044 {
00045   char riff[4];
00046   int length;
00047   char wave[4];
00048   char fmt[4];
00049   int lnginfo;
00050   short one;
00051   short channels;
00052   int freqechant;
00053   int bytespersec;
00054   short bytesperechant;
00055   short bitperchannel;
00056   char data[4];
00057   int datalength;
00058 };
00059 
00060 
00061 
00062 char * fname;
00063 int imcount;
00064 FILE *  file;
00065 bool outtodsp;
00066 bool withheader;
00067 bool waswithheader;
00068 int totallength;
00069 
00070 urbi::UCallbackAction
00071 endProgram(const urbi::UMessage&)
00072 {
00073   if (waswithheader)
00074   {
00075     //fclose(file);
00076     //file = fopen(fname, "w");
00077     // seek to set correct size in wav header
00078     if (fseek(file,offsetof(wavheader, length),SEEK_SET)==-1)
00079       {
00080         fprintf(stderr, "warning, can't seek output file (stdout?), wav header will be incorrect!\n");
00081         exit(0);
00082     }
00083     int len = totallength  - 8;
00084     fwrite(&len, 1, 4, file);
00085     fseek(file,offsetof(wavheader, datalength),SEEK_SET);
00086     len = totallength - 44;
00087     fwrite(&len, 1, 4, file);
00088     fclose(file);
00089     exit(0);
00090   }
00091   exit(0);
00092   return urbi::URBI_CONTINUE;
00093 }
00094 
00095 urbi::UCallbackAction
00096 getSound(const urbi::UMessage& msg)
00097 {
00098   static urbi::USound out;
00099   static bool initialized=false;
00100   if (!initialized)
00101   {
00102     totallength = 0;
00103     initialized = true;
00104     out.data = 0;
00105     out.size = 0;
00106     if (outtodsp)
00107     {
00108       out.channels = 2;
00109       out.sampleSize = 16;
00110       out.rate = 16000;
00111       out.sampleFormat = urbi::SAMPLE_SIGNED;
00112     }
00113     else
00114     {
00115       out.channels = 0;
00116       out.sampleSize = 0;
00117       out.rate = 0;
00118       out.sampleFormat = (urbi::USoundSampleFormat)0;
00119     }
00120   }
00121 
00122   if (msg.type != urbi::MESSAGE_DATA
00123       || msg.value->type != urbi::DATA_BINARY
00124       || msg.value->binary->type != urbi::BINARY_SOUND)
00125     return urbi::URBI_CONTINUE;
00126   out.soundFormat =
00127     withheader? urbi::SOUND_WAV : urbi::SOUND_RAW;
00128   withheader = false;
00129   convert(msg.value->binary->sound, out);
00130   totallength += out.size;
00131   fwrite(out.data, out.size, 1, file);
00132   return urbi::URBI_CONTINUE;
00133 }
00134 
00135 
00136 int main(int argc, char *argv[])
00137 {
00138   const char *usage = "usage:  urbisound robot milisecondtime  :plays sound recorded by the aibo to /dev/dsp\n"
00139     "\turbisound robot milisecondtime file [withoutheader] : write recorded sound to a file, with a wav header except if argument withoutheader is set to anything\n";
00140   //16000 1 16
00141   if (argc != 3)
00142   {
00143     printf(usage);
00144     exit(1);
00145   }
00146 
00147   int time = strtol(argv[2], NULL, 0);
00148 
00149   if (argc >= 4)
00150   {
00151     outtodsp = false;
00152     if (STREQ(argv[3],"-"))
00153       file=stdout;
00154     else
00155       file = fopen(argv[3], "wb+");
00156     fname = argv[3];
00157     if (file==0)
00158     {
00159       printf("error creating file\n");
00160       exit(2);
00161     }
00162 
00163     if (argc==5)
00164       withheader = false;
00165     else
00166       withheader = true;
00167   }
00168   else
00169   {
00170 #ifdef WIN32
00171     printf("output to soundcard not supported under windows\n");
00172     exit(2);
00173 #else
00174     outtodsp = true;
00175     withheader = false;
00176     file = fopen(device, "wb" );
00177     if (file==0)
00178     {
00179       printf("error opening device\n"), exit(2);
00180     }
00181     int f = fileno(file);
00182     int param;
00183 
00184     param=16;
00185     if (ioctl(f, SNDCTL_DSP_SAMPLESIZE, &param)==-1)
00186       {
00187         fprintf(stderr,"failed to set sample size for %s\n", device);
00188         exit(1);
00189       }
00190 
00191     param=1;
00192     if (ioctl (f, SNDCTL_DSP_STEREO, &param)==-1)
00193       {
00194         fprintf(stderr,"failed to set stereo for %s\n", device);
00195         exit(1);
00196       }
00197 
00198     param=16000;
00199     if (ioctl (f, SNDCTL_DSP_SPEED, &param) == -1)
00200       {
00201         fprintf(stderr,"failed to set speed for %s\n", device);
00202         exit(1);
00203       }
00204 #endif
00205   }
00206 
00207   waswithheader = withheader;
00208   urbi::UClient client (argv[1]);
00209   if (client.error())
00210     exit(0);
00211 
00212   client.setCallback(getSound, "usound");
00213   client.setCallback(endProgram, "end");
00214 
00215   client.send("loopsound:loop usound: micro.val ,"
00216               "{ wait(%d); stop loopsound; wait(1000); end:ping }, ", time);
00217   urbi::execute();
00218 }

Generated on Tue Apr 10 17:45:45 2007 for URBISDK by  doxygen 1.5.1