From: Steve K. <st...@st...> - 2003-10-31 21:02:38
|
Hey listers. You all probably thought I was dead, eh? Well, I figure Halloween was a good day to come back from the dead. Besides, this is the "eeeks"-client project, and today should have lots of "eeeks", right? I've been doing some iaxclient work lately, and figured I'd share what I've done with everyone, and also see if anyone is interested in helping with a couple of things. First, what I've already done: 1) Worked on another library-using client, which I'm not releasing yet, and probably won't be too interesting to anyone :) 2) Added sound-playing support to the library. The API is in iaxclient.h: struct iaxc_sound { short *data; /* sound data */ long len; /* length of sample */ int malloced; /* should the library free() the data after it is played? */ int repeat; /* number of times to repeat (-1 = infinite) */ long pos; /* internal use: current play position */ int id; /* internal use: sound ID */ struct iaxc_sound *next; /* internal use: next in list */ }; /* play a sound. sound = an iaxc_sound structure, ring: 0: play through output device; 1: play through "ring" device */ int iaxc_play_sound(struct iaxc_sound *sound, int ring); int iaxc_stop_sound(int id); The basic idea is that a library-user can do iax_play_sound, and pass a sound structure in, and the library will play that sound. It can cancel the playback of that particular sound by calling iaxc_stop_sound, with the id that was returned by play_sound. Currently, this is only implemented in the portaudio driver backend, and currently the "ring" parameter is ignored; it always plays back through the standard output device. You can convert a sox-compatible sound file into a C array at compile time with a program like sound2c.pl, also in the library sources. Or, you can make a ringback sound with some code like this: ringback.len = 6*8000; ringback.data = (short *)calloc(ringback.len , sizeof(short)); for( int i=0;i < 2*8000; i++ ) { ringback.data[i] = (short) (0x7fff * 0.3 * sin( (double) i * 440 * M_PI / 8000)); ringback.data[i] += (short) (0x7fff * 0.3 * sin( (double) i * 480 * M_PI / 8000 )); } ringback.repeat = 1; You can play multiple sounds together, and together with the output audio for a call. These are all mixed in the library before being sent to the sound drivers. 3) Added input/output volume level adjustments. Currently there are a bunch of caveats: Linux: Always adjusts /dev/mixer, which may or may not be the same as /dev/dsp, and may not be what you've chosen to use. Adjusts PCM output level, and capture level. MacOSX: Only works when sound is active (i.e. playing sound or in a call). Only some input devices have an adjustment available. Win32: Only works when sound is active. Only output level adjustment is currently implemented. The API for doing this is also in iaxclient.h 4) Added a hacky "file" audio driver, primarily for testing. the "testcall" client supports using this. ===================== Where people can help: 1) They can certainly feel free to implement these features in their own clients (iaxcomm, etc). Volume control is definately something that people might want there, and the code do use it is pretty simple. 2) The sound mechanism can be extended to: a) support the "ring" parameter, to play back through a possibly different ring device. 3) The library can be extended to use the sound mechanism to support: a) ringing on incoming calls. b) ringback on outgoing calls. c) dial/error or other tones people might want to hear? 4) If one of the windows-dudes can see how to implement input level control, that would be much appreciated. It seems to be about 10x harder to do than output-level control, which is just waveOutGetVolume/ waveOutSetVolume. Look in lib/portaudio/pa_win_wmme/pa_win_wmme.c for where the code would go. [Also, I think that this is somewhat implemented in portaudio v19, so we may be able to leverage that]. 5) Another feature I need to add to the library [and this might actually end up needing to go into libiax2, instead of libiaxclient] is to have the client send PING frames to the far end of calls, and then expect PONG frames back. If a PONG doesn't come back after repeated PING retransmissions, the client should get some kind of notification. Currently, if the other end of a call disappears, iaxclient never knows about this. -SteveK |