Newer
Older
Import / research / embedded / src / library / sound.c
/*
Copyright (c) 2007-2013, John Ryland
*/
#include <oslayer.h>
#include <corelayer.h>
#include <soundcard.h>
#include <sound.h>

const char *formatTable[] = {
	"AFMT_MU_LAW",
	"AFMT_A_LAW",
	"AFMT_IMA_ADPCM",
	"AFMT_U8",			/* unsigned 8 */
	"AFMT_S16_LE",  /* Little endian signed 16*/
	"AFMT_S16_BE",  /* Big endian signed 16 */
	"AFMT_S8",			/* signed 8 */
	"AFMT_U16_LE",  /* Little endian U16 */
	"AFMT_U16_BE",  /* Big endian U16 */
	"AFMT_MPEG",	/* MPEG (2) audio */
	"AFMT_AC3"			/* Dolby Digital AC3 */
};

void printAudioFormatMask(int format, const char *sep)
{
	int i = 0;
	int first = 0;
	while (format) {
		if (format & 0x01) {
			if (first)
				strPrint(sep);
			strPrint(formatTable[i]);
			first = 1;
		}
		i++;
		format >>= 1;
	}
}

const char *levelNames[] = SOUND_DEVICE_LABELS;

#undef MIXER_WRITE
#define MIXER_WRITE(d)		_IOW('M', d, int)

void setVolume(int arg)
{
	int mixerFd = fsOpen("/dev/sound/mixer", O_RDWR);
	int mute = 0;
	int mask = 0;
	int vol, i;
	int buf[256];
	mixer_vol_table		tab;
	mixer_info				info;
	_old_mixer_info		old_info;
/*
	if (sysIoctl(mixerFd, SOUND_MIXER_WRITE_MUTE, &mute))
		strPrint("error in call mute\n");
	if (sysIoctl(mixerFd, MIXER_READ(SOUND_MIXER_OUTMASK), &mask))
		strPrint("error in call MIXER_READ(SOUND_MIXER_OUTMASK)\n");
		strPrintf("got MIXER_READ(SOUND_MIXER_OUTMASK) = %x\n", mask);
	if (sysIoctl(mixerFd, MIXER_WRITE(SOUND_MIXER_OUTSRC), &mask))
		strPrint("error in call MIXER_WRITE(SOUND_MIXER_OUTSRC)\n");
*/

/*
success: _IOC(0, T, 33, 0)
success: _IOC(0, T, 80, 0)
success: _IOC(0, T, 81, 0)
success: _IOC(0, T, 82, 0)

success: _IOW(M, 9, 4)				// SOUND_MIXER_WRITE_IMIX
success: _IOW(M, 11, 4)				// SOUND_MIXER_WRITE_RECLEV
success: _IOW(M, 13, 4)				// SOUND_MIXER_WRITE_OGAIN
success: _IOR(M, 6, 4)				// SOUND_MIXER_READ_LINE
success: _IOR(M, 8, 4)				// SOUND_MIXER_READ_CD
success: _IOR(M, 10, 4)				// SOUND_MIXER_READ_ALTPCM
success: _IOR(M, 12, 4)				// SOUND_MIXER_READ_IGAIN
success: _IOR(M, 14, 4)				// SOUND_MIXER_READ_LINE1
success: _IOR(M, 101, 48)		// SOUND_OLD_MIXER_INFO
success: _IOR(M, 101, 92)		// SOUND_MIXER_INFO
success: _IOR(M, 118, 4)		// OSS_GETVERSION
success: _IORW(M, 116, 164)		// SOUND_MIXER_GETLEVELS
success: _IORW(M, 117, 164)		// SOUND_MIXER_SETLEVELS

  char id[16];
  char name[32];
  int  modify_counter;
  int fillers[10];
*/

/*
	if (sysIoctl(mixerFd, SOUND_MIXER_GETLEVELS, &tab))
		strPrint("error in call X\n");

	strPrintf("audio:  name: %s  num: %i\n", tab.name, -tab.num);
	for (i = 0; i < 32; i++) {
		strPrintf("level[%i]:  %x\n", i, tab.levels[i]);
		tab.levels[i] = arg;
	}

	fsClose(mixerFd);
	mixerFd = fsOpen("/dev/sound/mixer", O_RDWR);

	if (sysIoctl(mixerFd, SOUND_MIXER_SETLEVELS, &tab))
		strPrint("error in call Y\n");

//	if (sysIoctl(mixerFd, _IO('T', 33), 0))
//		strPrint("error in call 1\n");
	if (sysIoctl(mixerFd, _IO('T', 80), 0))
		strPrint("error in call 2\n");
	if (sysIoctl(mixerFd, _IO('T', 81), 0))
		strPrint("error in call 3\n");
//	if (sysIoctl(mixerFd, _IO('T', 82), 0))
//		strPrint("error in call 4\n");
*/

	vol = arg;
	if (sysIoctl(mixerFd, _IOW('M', 5, 4), &vol)) // SOUND_MIXER_SPEAKER
		strPrint("error in call vA--\n");
	vol = arg;
	if (sysIoctl(mixerFd, _IOW('M', 7, 4), &vol)) // SOUND_MIXER_MIC
		strPrint("error in call vA--\n");
	vol = arg;//(90 << 8) | 90;
	if (sysIoctl(mixerFd, SOUND_MIXER_WRITE_IMIX, &vol))
		strPrint("error in call vB\n");
	vol = arg;
	if (sysIoctl(mixerFd, SOUND_MIXER_WRITE_RECLEV, &vol))
		strPrint("error in call vA--\n");
	vol = arg;//(90 << 8) | 90;
	if (sysIoctl(mixerFd, SOUND_MIXER_WRITE_OGAIN, &vol))
		strPrint("error in call vB\n");

	vol = (90 << 8) | 90;
	if (sysIoctl(mixerFd, SOUND_MIXER_READ_LINE, &vol))
		strPrint("error in call vB\n");
	strPrintf("line vol: %i\n", i);
	vol = (90 << 8) | 90;
	if (sysIoctl(mixerFd, SOUND_MIXER_READ_CD, &vol))
		strPrint("error in call vB\n");
	strPrintf("cd vol: %i\n", i);
	vol = (90 << 8) | 90;
	if (sysIoctl(mixerFd, SOUND_MIXER_READ_ALTPCM, &vol))
		strPrint("error in call vB\n");
	strPrintf("altpcm vol: %i\n", i);
	vol = (90 << 8) | 90;
	if (sysIoctl(mixerFd, SOUND_MIXER_READ_IGAIN, &vol))
		strPrint("error in call vB\n");
	strPrintf("igain vol: %i\n", i);
	vol = (90 << 8) | 90;
	if (sysIoctl(mixerFd, SOUND_MIXER_READ_LINE1, &vol))
		strPrint("error in call vB\n");
	strPrintf("line1 vol: %i\n", i);

	fsClose(mixerFd);
}


int openSound()
{
#if defined(ARCH_ARM)
	int audioFd = fsOpen("/dev/sound/dsp1", O_RDWR);
#else
	int audioFd = fsOpen("/dev/dsp", O_RDWR);
#endif
	int format = AFMT_S16_LE, stereo = 1, speed = 8000;//48000;//11025;
	int frags = 0x0002000A, mask;
	int ver = 1;

	//setVolume(32);

//	int pm = fsOpen("/dev/pm", O_RDWR);
//	int lcdFd = fsOpen("/dev/fb0", O_RDWR);
//	sysIoctl(pm, SNDCTL_DSP_SETFRAGMENT, 0);
//	sysIoctl(lcdFd, 0x4d0d, 0);
//	fsClose(lcdFd);
//	lcdFd = fsOpen("/dev/fb0", O_RDWR);
//	sysIoctl(lcdFd, 0x4d21, 0);
//	fsClose(pm);
//	fsClose(lcdFd);

	if (sysIoctl(audioFd, OSS_GETVERSION, &ver))
		strPrint("OSS_GETVERSION error in call\n");
	if (sysIoctl(audioFd, SNDCTL_DSP_SETFRAGMENT, &frags))
		strPrint("SNDCTL_DSP_SETFFRAGMENT error in call\n");
	if (sysIoctl(audioFd, SNDCTL_DSP_SETFMT, &format) == -1)
		strPrint("SNDCTL_DSP_SETFMT error in call\n");
	if (format != AFMT_S16_LE)
		strPrint("SNDCTL_DSP_SETFMT error, format not supported\n");
	if (sysIoctl(audioFd, SNDCTL_DSP_GETFMTS, &mask) != -1) {
		strPrint("Supported audio formats: ");
		printAudioFormatMask(mask, ", ");
		strPrint("\n");
	}
	if (sysIoctl(audioFd, SNDCTL_DSP_STEREO, &stereo) == -1)
		strPrint("SNDCTL_DSP_STEREO error in call\n");
	if (sysIoctl(audioFd, SNDCTL_DSP_SPEED, &speed) == -1)
		strPrint("SNDCTL_DSP_SPEED error in call\n");

//	strPrint("Sound parameters are: ");
//	printAudioFormatMask(format, "|");
	strPrintf("Sound parameters:\n  OSS-Version: %x\n  %s %iHz\n", ver, stereo ? "stereo" : "mono", speed);

	return audioFd;
}

void closeSound(int audioFd)
{
	fsClose(audioFd);
}

Sound openSoundFile(const char *mapableSound)
{
	stat sbuf;
	Sound sound;
	sound.fd = fsOpen(mapableSound, O_RDONLY);
	fsStat(mapableSound, &sbuf);
	sound.data = (unsigned char *)fsMmap(0, sbuf.st_size, PROT_READ, MAP_PRIVATE, sound.fd, 0);
	sound.size = sbuf.st_size;
	return sound;
}

void closeSoundFile(Sound sound)
{
	fsClose(sound.fd);
}

void playSound(int sd, Sound *sound)
{
	unsigned char blank[1024];
	int i;
	fsWrite(sd, sound->data, sound->size);
	for (i = 0; i < 1024; i++)
		blank[i] = 0;
	fsWrite(sd, blank, sound->size % 1024); // Close off a fragment
//	sysIoctl(sd, SNDCTL_DSP_POST, 0);
//	sysIoctl(sd, SNDCTL_DSP_SYNC, 0);
}

void playSoundFile(int sd, const char *mapableSound)
{
	stat sbuf;
	unsigned char *ch;
	unsigned char blank[1024];
	int i, fd = fsOpen(mapableSound, O_RDONLY);
	fsStat(mapableSound, &sbuf);
	ch = (unsigned char *)fsMmap(0, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	fsWrite(sd, ch, sbuf.st_size);
//	sysIoctl(sd, SNDCTL_DSP_POST, 0);
//	sysIoctl(sd, SNDCTL_DSP_SYNC, 0);
	for (i = 0; i < 1024; i++)
		blank[i] = 0;
	fsWrite(sd, blank, sbuf.st_size % 1024); // Close off a fragment
	fsClose(fd);
}