Sound Input


fells

Still Fresh
Joined
Jul 6, 2009
Messages
39
I am about to start writing some code that does real time sound in/out. Before I embark on it does anyone have any experience here on the Wiz?

The voice recorder app seems to record at 16-bit 48Khz stereo, which is nice, but obviously the electret mic is a mono thing with probably crap freq response.

I was hoping the headphone jack is also a headset input but so far none of my 3-lead headset mic/phone kits (like iphone headsets etc) work as a mic. That's OK though. Maybe one of the ext pins is sound in?

Does anyone know if the Wiz comes with OSS support baked in?
 
Was able to get simple OSS 3.0 sound output programs compiled and run, but not sound input yet.

The sound input programs compile and seem to run fine but I'm not seeing any useful audio data coming into them. Anything that opens a sound in channels shows me

Code:
HYUN_DEBUG: pollux_audio_open()
HYUN_DEBUG: AUDION IN  ....

but then no data comes in.

OSS 4.0 (mixer and stuff) is not supported it seems, so I can't easily look at what "recording select" is set to or see a quick mixer view.

Still playing around, will update when i know more.
 
OK, I got it. Had to look at the pollux driver source as there's a couple of weird OSS bugs they introduced. But it's easy. Here's the source of a "homebrew sound recorder" (not very useful, but just illustrative.)

You need soundcard.h, which is in the openwiz toolchain somewhere. I couldn't get the compiler to find it without it breaking everything else, so I just copied it to my source code folder. I used the same makefile as I used in my "simple SDL example" post.

After compiling, run it like
Code:
./test-sdl.gpe filename.raw

and it will record 10s from the microphone as a raw 22050 stereo file. Open this in audacity as 16 signed pcm, little endian, 22050, stereo.

Code:
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <soundcard.h>
#include <stdio.h>
#include <stdlib.h>


/* Example of how to read input from C on the gp2x wiz */
/* by fells on gp32x.de */

static int mixer_fd = -1;
int fd_in;
FILE* file_out;
float seconds = 0;
#define SAMPLE_RATE 22050
#define BUF_SAMPLES 16384

static int mixer_open(const char *device) {
        mixer_fd = open(device, O_RDWR);
        if (mixer_fd == -1) return -1;
	return 0;
}

static int mixer_set_recsrc(int channel) {
	if(ioctl(mixer_fd, SOUND_MIXER_WRITE_RECSRC, &channel) == -1) return -1;
	return 0;
}

static int mixer_set_level(int channel, int l, int r) {
        int tmp;
        tmp = (l & 0x7f) + ((r & 0x7f) << 8);
        if (ioctl(mixer_fd, MIXER_WRITE(channel), &tmp) == -1) return -1;
        return 0;
}

static int open_audio_device (char *name, int mode) {
	int fd;
	if ((fd = open (name, mode, 0)) == -1) {
		perror (name);
		exit (-1);
	}
	int format = AFMT_S16_NE;		/* Native 16 bits */
	if (ioctl (fd, SNDCTL_DSP_SETFMT, &format) == -1)   {
		perror ("SNDCTL_DSP_SETFMT");
		exit (-1);
	}
	int channels = 2; // have to use 2 channels on pollux
	if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
		perror ("SNDCTL_DSP_CHANNELS");
		exit (-1);
	}
	int sample_rate = SAMPLE_RATE;
	if (ioctl (fd, SNDCTL_DSP_SPEED, &sample_rate) == -1) {
		perror ("SNDCTL_DSP_SPEED");
		exit (-1);
	}
	return fd;
}


void process_input (void) {
	short buffer[BUF_SAMPLES];
	int bytes_read, samples_read, frames_read, i, level_min, level_max;
	if ((bytes_read = read (fd_in, buffer, sizeof (buffer))) == -1) {
		perror ("Audio read");
		exit (-1);		/* Or return an error code */
	}
	samples_read = bytes_read / 2; // 2 bytes per sample
	frames_read = samples_read / 2; // because we are reading stereo data
	level_max = 0;
	level_min = 16384;
	for (i = 0; i < samples_read; i=i+1) {
		int v = buffer[i];
		if (v > level_max) level_max = v;
		if(v < level_min) level_min = v;
	}
	fwrite(buffer, sizeof(short), samples_read, file_out);
	fflush (stdout);
	seconds = seconds + ((float)frames_read/22050.0);
	printf("(%d,%d) %2.2f\n", level_min, level_max,seconds);
}


int main(int argc, char**argv) {
	int i;
	// Open the mixer and the audio device
	i = mixer_open("/dev/mixer");
	fd_in = open_audio_device ("/dev/dsp", O_RDONLY);

	// Set the recording source to mic
	i = mixer_set_recsrc(SOUND_MIXER_MIC);
	i = mixer_set_level(SOUND_MIXER_VOLUME, 100, 100);

	// Debug note: there seems to be a bug in the pollux driver that the mic setting can't be "gotten"
	// with the SOUND_MIXER_MIC -- for some reason, you need to get the mixer gain with SOUND_MIXER_LINE
	// But you should still set the gain with SOUND_MIXER_MIC. See pollux-cs42L51.c
	i = mixer_set_level(SOUND_MIXER_MIC, 85, 85); // the built in voice recorder sets mixer vol to 85 too

	sleep(1);
	char filename[255];
	if(argc != 2) {
		strcpy(filename, "/mnt/sd/out-sound.raw");
	} else {
		strcpy(filename, argv[1]);
	}
	file_out = fopen(filename,"w");

	// Start recording
	while (seconds < 10)
	    process_input ();
	fclose(file_out);

	exit (0);
}
 
Last edited by a moderator:
Of note is the source for the audio driver lists two mixer inputs -- line and mic, but the "recSel" parameter seems to be ignored and no matter which you set it to the same input is used (the onboard mic.) A pity as I was hoping for some line in action on the EXT port. Also, stereo is hardcoded in both directions (in and out) even though the mic is mono. Sampling rates go up to 64000 !
 
One weirdness to watch for is that the fragsize seems to be locked at 32768 bytes. The driver source does accept different fragsizes but the default is 32768 and if you try to do a read of less than 32768 bytes you get garbage data way too fast (10x real time.) I think (think) this is a bug in the pollux OSS drivers (the code is realllly raw & messy) so hopefully if we get to building our own rootfs we can try to fix it.

Doing the SETFRAGMENT business seems to have no effect, e.g

int fragment = (nbfrags << 16) | (1<<(BUF_SAMPLES*2));
iotctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragment);

does not help at all. The Wiz sound in seems to locked at a fragsize of 32768... which is 0.37s of latency at 44100... urgh
 
This is excellent progress fells, I look forward to hacking together my own app (would be nice to make a sampler) and for sure I'll be learning from your work soon as I get time for another WIZ hacking session .. Great stuff, keep it up!
 
yeah. the bufsize thing is real problematic for what I wanted to do, but if I'm right it should be a quick fix once we've got a way to compile & load our own kernel in. I'll also fix the mixer reporting while I'm at it :)

I actually just got a $9 cheapo USB audio adapter, I'm going to try to wire it to USB host maybe later tonight to see if anything good happens. At least then you're at the mercy of a non-GPH written driver :)
 
Back
Top