--- speexclient/speexclient.c 2010-09-03 12:44:29.890652316 -0400 +++ speexclient-vogue/speexclient.c 2010-09-03 18:12:11.470922456 -0400 @@ -46,7 +46,19 @@ #include /* close() */ #include /* memset() */ -#include "alsa_device.h" +/* #include "alsa_device.h" */ + +/* begin playwav2.c paste */ + +#include +#include +#include +#include + +#include + +/* end playwav2.c paste */ + #include #include #include @@ -55,9 +67,213 @@ #include +/* begin playwav2.c paste */ + +#if 0 +#include +#else +/* ---------- linux/msm_audio.h -------- */ + +#define AUDIO_IOCTL_MAGIC 'a' + +#define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned) +#define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned) +#define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned) +#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned) +#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned) +#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned) +#define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned) +#define AUDIO_SET_ADRC _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned) +#define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned) +#define AUDIO_SET_RX_IIR _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned) + +#define EQ_MAX_BAND_NUM 12 + +#define ADRC_ENABLE 0x0001 +#define ADRC_DISABLE 0x0000 +#define EQ_ENABLE 0x0002 +#define EQ_DISABLE 0x0000 +#define IIR_ENABLE 0x0004 +#define IIR_DISABLE 0x0000 + +struct eq_filter_type +{ + int16_t gain; + uint16_t freq; + uint16_t type; + uint16_t qf; +}; + +struct eqalizer +{ + uint16_t bands; + uint16_t params[132]; +}; + +struct rx_iir_filter +{ + uint16_t num_bands; + uint16_t iir_params[48]; +}; + + +struct msm_audio_config +{ + uint32_t buffer_size; + uint32_t buffer_count; + uint32_t channel_count; + uint32_t sample_rate; + uint32_t codec_type; + uint32_t unused[3]; +}; + +struct msm_audio_stats +{ + uint32_t out_bytes; + uint32_t unused[3]; +}; + +/* Audio routing */ + +#define SND_IOCTL_MAGIC 's' + +#define SND_MUTE_UNMUTED 0 +#define SND_MUTE_MUTED 1 + +struct msm_snd_device_config +{ + uint32_t device; + uint32_t ear_mute; + uint32_t mic_mute; +}; + +#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *) + +#define SND_METHOD_VOICE 0 + +#define SND_METHOD_VOICE_1 1 + +struct msm_snd_volume_config +{ + uint32_t device; + uint32_t method; + uint32_t volume; +}; + +#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *) + +/* Returns the number of SND endpoints supported. */ + +#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *) + +struct msm_snd_endpoint +{ + int id; /* input and output */ + char name[64]; /* output only */ +}; + +/* Takes an index between 0 and one less than the number returned by + * SND_GET_NUM_ENDPOINTS, and returns the SND index and name of a + * SND endpoint. On input, the .id field contains the number of the + * endpoint, and on exit it contains the SND index, while .name contains + * the description of the endpoint. + */ + +#define SND_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_snd_endpoint *) + +#endif +/* ---------- -------- */ + +static int +do_route_audio_rpc (uint32_t device, int ear_mute, int mic_mute) +{ + if (device == -1UL) + return 0; + + int fd; + + printf ("rpc_snd_set_device(%d, %d, %d)\n", device, ear_mute, mic_mute); + + fd = open ("/dev/msm_snd", O_RDWR); + if (fd < 0) + { + perror ("Can not open snd device"); + return -1; + } + // RPC call to switch audio path + /* rpc_snd_set_device( + * device, # Hardware device enum to use + * ear_mute, # Set mute for outgoing voice audio + * # this should only be unmuted when in-call + * mic_mute, # Set mute for incoming voice audio + * # this should only be unmuted when in-call or + * # recording. + * ) + */ + struct msm_snd_device_config args; + args.device = device; + args.ear_mute = ear_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED; + args.mic_mute = mic_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED; + + if (ioctl (fd, SND_SET_DEVICE, &args) < 0) + { + perror ("snd_set_device error."); + close (fd); + return -1; + } + + close (fd); + return 0; +} + +static int +set_volume_rpc (uint32_t device, uint32_t method, uint32_t volume) +{ + int fd; + + printf ("rpc_snd_set_volume(%d, %d, %d)\n", device, method, volume); + + if (device == -1UL) + return 0; + + fd = open ("/dev/msm_snd", O_RDWR); + if (fd < 0) + { + perror ("Can not open snd device"); + return -1; + } + /* rpc_snd_set_volume( + * device, # Any hardware device enum, including + * # SND_DEVICE_CURRENT + * method, # must be SND_METHOD_VOICE to do anything useful + * volume, # integer volume level, in range [0,5]. + * # note that 0 is audible (not quite muted) + * ) + * rpc_snd_set_volume only works for in-call sound volume. + */ + struct msm_snd_volume_config args; + args.device = device; + args.method = method; + args.volume = volume; + + if (ioctl (fd, SND_SET_VOLUME, &args) < 0) + { + perror ("snd_set_volume error."); + close (fd); + return -1; + } + close (fd); + return 0; +} + +static char *next; +static unsigned avail; + +/* end playwav2.c paste */ + #define MAX_MSG 1500 -#define SAMPLING_RATE 16000 +#define SAMPLING_RATE 8000 #define FRAME_SIZE 320 int main(int argc, char *argv[]) @@ -72,7 +288,7 @@ int nfds; struct pollfd *pfds; SpeexPreprocessState *preprocess; - AlsaDevice *audio_dev; + /*AlsaDevice *audio_dev;*/ int tmp; if (argc != 5) @@ -118,16 +334,69 @@ } /* Setup audio device */ - audio_dev = alsa_device_open(argv[1], SAMPLING_RATE, 1, FRAME_SIZE); - + /* audio_dev = alsa_device_open(argv[1], SAMPLING_RATE, 1, FRAME_SIZE); */ + +/* begin playwav2.c paste */ + + int fd = open ("/dev/msm_snd", O_RDWR); + int mNumSndEndpoints; + + if (fd >= 0) + { + int rc = ioctl (fd, SND_GET_NUM_ENDPOINTS, + &mNumSndEndpoints); + + printf ("found %d snd endpoints\n", mNumSndEndpoints); + + if (rc >= 0) + { + struct msm_snd_endpoint ept; + int cnt; + + for (cnt = 0; cnt < mNumSndEndpoints; cnt++) + { + ept.id = cnt; + ioctl (fd, SND_GET_ENDPOINT, &ept); + printf (" %02d: %s / %d\n", cnt, ept.name, ept.id); + } + } + else + perror ("Could not retrieve number of MSM SND endpoints."); + close (fd); + } + else + perror ("Could not open MSM SND driver."); + + printf ("Select device %d.\n", 0); + +// do_route_audio_rpc (0, SND_MUTE_MUTED, SND_MUTE_MUTED); + do_route_audio_rpc(0,SND_MUTE_UNMUTED,SND_MUTE_UNMUTED); + + +// printf ("enable PP\n"); +// msm72xx_enable_audpp(ADRC_ENABLE | EQ_ENABLE | IIR_ENABLE); + + printf ("Set master volume to %d.\n", 5); +#if 0 + set_volume_rpc (SND_DEVICE_HANDSET, SND_METHOD_VOICE, vol); + set_volume_rpc (SND_DEVICE_SPEAKER, SND_METHOD_VOICE, vol); + set_volume_rpc (SND_DEVICE_BT, SND_METHOD_VOICE, vol); + set_volume_rpc (SND_DEVICE_HEADSET, SND_METHOD_VOICE, vol); +#endif + + /* dev=0xd ? */ + set_volume_rpc (0xd, SND_METHOD_VOICE_1, 5); + +/* end playwav2.c paste */ + /* Setup the encoder and decoder in wideband */ void *enc_state, *dec_state; - enc_state = speex_encoder_init(&speex_wb_mode); + enc_state = speex_encoder_init(&speex_nb_mode); tmp = 8; speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &tmp); tmp = 2; speex_encoder_ctl(enc_state, SPEEX_SET_COMPLEXITY, &tmp); - dec_state = speex_decoder_init(&speex_wb_mode); + dec_state = speex_decoder_init(&speex_nb_mode); tmp = 1; speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &tmp); SpeexBits enc_bits, dec_bits; @@ -145,9 +414,14 @@ int recv_started=0; /* Setup all file descriptors for poll()ing */ - nfds = alsa_device_nfds(audio_dev); + /* nfds = alsa_device_nfds(audio_dev); */ + nfds = 2; pfds = malloc(sizeof(*pfds)*(nfds+1)); - alsa_device_getfds(audio_dev, pfds, nfds); + /* alsa_device_getfds(audio_dev, pfds, nfds); */ + pfds[0].fd = open("/dev/msm_pcm_in", O_RDWR); + pfds[0].events = POLLIN; + pfds[1].fd = open("/dev/msm_pcm_out", O_RDWR); + pfds[1].events = POLLOUT; pfds[nfds].fd = sd; pfds[nfds].events = POLLIN; @@ -164,8 +438,104 @@ preprocess = speex_preprocess_state_init(FRAME_SIZE, SAMPLING_RATE); speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, echo_state); - alsa_device_start(audio_dev); - + /* alsa_device_start(audio_dev); */ + +/* begin playwav2.c paste */ + +// unsigned char buf[8192]; + unsigned char buf[320] + struct msm_audio_config cfg; + unsigned sz; + unsigned total = 0; + + if (pfds[0].fd < 0) + { + perror ("cannot open msm_pcm_in"); + return -1; + } + + /* config change should be a read-modify-write operation */ + if (ioctl (pfds[0].fd, AUDIO_GET_CONFIG, &cfg)) + { + perror ("cannot read write audio config"); + return -1; + } + + cfg.channel_count = 1; + cfg.sample_rate = 8000; + cfg.buffer_size = 320; + if (ioctl (pfds[0].fd, AUDIO_SET_CONFIG, &cfg)) + { + perror ("cannot write write audio config"); + return -1; + } + + if (ioctl (pfds[0].fd, AUDIO_GET_CONFIG, &cfg)) + { + perror ("cannot read write audio config"); + return -1; + } + + sz = cfg.buffer_size; + fprintf (stderr, "write buffer size %d x %d\n", sz, cfg.buffer_count); + if (sz > sizeof (buf)) + { + fprintf (stderr, "write buffer size %d too large\n", sz); + return -1; + } + + if (ioctl (pfds[0].fd, AUDIO_START, 0)) + { + perror ("cannot start write audio"); + return -1; + } + + struct msm_audio_config config; + struct msm_audio_stats stats; + unsigned sz2; + char buf2[320]; + + if (pfds[1].fd < 0) + { + perror ("pcm_play: cannot open audio device"); + return -1; + } + + if (ioctl (pfds[1].fd, AUDIO_GET_CONFIG, &config)) + { + perror ("could not get read config"); + return -1; + } + + config.channel_count = 1; + config.sample_rate = 8000; + config.buffer_size = 320; + if (ioctl (pfds[1].fd, AUDIO_SET_CONFIG, &config)) + { + perror ("could not set read config"); + return -1; + } + sz2 = config.buffer_size; + if (sz2 > sizeof (buf2)) + { + fprintf (stderr, "read buffer too big\n"); + return -1; + } + +/* fprintf (stderr, "prefill\n"); + for (n = 0; n < config.buffer_count; n++) + { + if (fill (buf, sz, cookie)) + break; + if (write (afd, buf, sz) != sz) + break; + } */ + + ioctl (pfds[1].fd, AUDIO_START, 0); + + +/* end playwav2.c paste */ + /* Infinite loop on capture, playback and receiving packets */ while (1) { @@ -188,8 +558,8 @@ } /* Ready to play a frame (playback) */ - if (alsa_device_playback_ready(audio_dev, pfds, nfds)) - { +// if (alsa_device_playback_ready(audio_dev, pfds, nfds)) +// { short pcm[FRAME_SIZE]; if (recv_started) { @@ -200,18 +570,24 @@ pcm[i] = 0; } /* Playback the audio and reset the echo canceller if we got an underrun */ - if (alsa_device_write(audio_dev, pcm, FRAME_SIZE)) +// if (alsa_device_write(audio_dev, pcm, FRAME_SIZE)) +#if 0 + if (ioctl (pfds[1].fd, AUDIO_GET_STATS, &stats) == 0) + fprintf (stderr, "%10d\n", stats.out_bytes); +#endif + if (write (pfds[1].fd, pcm, FRAME_SIZE)) speex_echo_state_reset(echo_state); /* Put frame into playback buffer */ speex_echo_playback(echo_state, pcm); - } +// } /* Audio available from the soundcard (capture) */ - if (alsa_device_capture_ready(audio_dev, pfds, nfds)) - { +// if (alsa_device_capture_ready(audio_dev, pfds, nfds)) +// { short pcm[FRAME_SIZE], pcm2[FRAME_SIZE]; char outpacket[MAX_MSG]; /* Get audio from the soundcard */ - alsa_device_read(audio_dev, pcm, FRAME_SIZE); +// alsa_device_read(audio_dev, pcm, FRAME_SIZE); + read (pfds[0].fd, pcm, FRAME_SIZE); /* Perform echo cancellation */ speex_echo_capture(echo_state, pcm, pcm2); @@ -240,7 +616,7 @@ close(sd); exit(1); } - } +// } }