You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/kscd/kscdmagic/sound.cpp

253 lines
6.4 KiB

/* Synaesthesia - program to display sound graphically
Copyright (C) 1997 Paul Francis Harrison
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The author may be contacted at:
pfh@yoyo.cc.monash.edu.au
or
27 Bond St., Mt. Waverley, 3149, Melbourne, Australia
*/
#if defined(__linux__) || defined(__svr4__)
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#if defined (__linux__)
#include <linux/soundcard.h>
#ifndef __GNUC__
#define __GNUC__ 1
#endif
#undef __STRICT_ANSI__
#include <asm/types.h>
#include <linux/cdrom.h>
#endif
#if defined (__svr4__)
#include <sys/soundcard.h>
#endif
// who knows when we'll need that...
#if defined (FreeBSD)
#include <sys/soundcard.h>
#include <sys/cdio.h>
#define CDROM_LEADOUT 0xAA
#define CD_FRAMES 75 /* frames per second */
#define CDROM_DATA_TRACK 0x4
#endif
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "syna.h"
#include "magicconf.h"
/* Sound Recording ================================================= */
#ifdef LITTLEENDIAN
#define SOUNDFORMAT AFMT_S16_LE
#else
#define SOUNDFORMAT AFMT_S16_BE
#endif
//If kernel starts running out of sound memory playing mp3s, this could
//be the problem. OTOH if it is too small, it will start ticking on slow
//computers
#define MAXWINDOWSIZE 32
static SoundSource source;
static int inFrequency, downFactor, windowSize, pipeIn, device;
static short *dataIn;
static char *mixer;
void
openSound(SoundSource source, int inFrequency, const char *dspName,
char *mixerName)
{
::source = source;
::inFrequency = inFrequency;
::windowSize = 1;
mixer = mixerName;
downFactor = inFrequency / frequency;
if (downFactor <= 0)
downFactor = 1;
int format, stereo, fragment, fqc;
#ifdef __FreeBSD__
attempt(device = open(dspName,O_WRONLY),"opening dsp device",true);
format = SOUNDFORMAT;
attempt(ioctl(device,SNDCTL_DSP_SETFMT,&format),"setting format",true);
if (format != SOUNDFORMAT) error("setting format (2)");
close(device);
#endif
if (source == SourcePipe)
attempt(device = open(dspName,O_WRONLY),"opening dsp device",true);
else
attempt(device = open(dspName,O_RDONLY),"opening dsp device",true);
//Probably not needed
//attemptNoDie(ioctl(device,SNDCTL_DSP_RESET,0),"reseting dsp");
format = SOUNDFORMAT;
fqc = (source == SourcePipe ? inFrequency : frequency);
stereo = 1;
//int logWindowSize = -1, tmp = windowSize*downFactor;
//while(tmp) {
// tmp /= 2;
// logWindowSize++;
//}
if (source == SourcePipe)
//fragment = 0x00020000 + (m-overlap+1)+logWindowSize;
fragment = 0x00010000*(MAXWINDOWSIZE+1) + (m-overlap+1);//+logWindowSize;
//Soundcard should read in windowSize
// blocks of sound before blocking
else
//fragment = 0x00020000 + (m-overlap+1); //2 fragments of size 2*(2^(m-overlap+1)) bytes
//Added extra fragments to allow recording overrun (9/7/98)
fragment = 0x00080000 + (m-overlap+1); //8 fragments of size 2*(2^(m-overlap+1)) bytes
//Was 0x00010000 + m;
attemptNoDie(ioctl(device,SNDCTL_DSP_SETFRAGMENT,&fragment),"setting fragment",true);
#ifndef __FreeBSD__
attempt(ioctl(device,SNDCTL_DSP_SETFMT,&format),"setting format",true);
if (format != SOUNDFORMAT) error("setting format (2)");
#endif
attempt(ioctl(device,SNDCTL_DSP_STEREO,&stereo),"setting stereo",true);
attemptNoDie(ioctl(device,SNDCTL_DSP_SPEED,&fqc),"setting frequency",true);
data = new short[n*2];
if (source == SourcePipe) {
dataIn = new short[n*2*downFactor*MAXWINDOWSIZE];
memset(dataIn,0,n*4*downFactor*MAXWINDOWSIZE);
pipeIn = dup(0);
close(0);
}
}
void closeSound() {
delete data;
if (source == SourcePipe) {
delete dataIn;
close(pipeIn);
}
close(device);
}
int readWholeBlock(int pipe,char *dest,int length) {
while(length > 0) {
int result = read(pipe,dest,length);
if (result < 1)
return -1;
dest += result;
length -= result;
}
return 0;
}
int getNextFragment(void) {
if (source == SourcePipe) {
static int lastTime = 0;
int nowTime;
timeval timeVal1, timeVal2;
gettimeofday(&timeVal1,0);
write(device, (char*)dataIn, n*4*downFactor*windowSize);
gettimeofday(&timeVal2,0);
nowTime = timeVal1.tv_usec + timeVal1.tv_sec * 1000000;
if (nowTime > lastTime) {
int optimumFrags =
int(double(nowTime-lastTime)*inFrequency/1000000.0/(n*downFactor))
+1;
if (optimumFrags > MAXWINDOWSIZE)
optimumFrags = MAXWINDOWSIZE;
windowSize = optimumFrags;
}
lastTime = timeVal2.tv_usec + timeVal2.tv_sec * 1000000;
if (readWholeBlock(pipeIn, ((char*)dataIn), n*4*downFactor*windowSize) == -1)
return -1;
int i,j;
for(i=0,j=0;i<n;i++,j+=downFactor)
((long*)data)[i] = ((long*)dataIn)[j];
} else {
int i;
count_info info;
if (-1 == ioctl(device,SNDCTL_DSP_GETIPTR,&info))
info.blocks = 1;
if (info.blocks > 8 || info.blocks < 1) /* Sanity check */
info.blocks = 1;
for(i=0;i<info.blocks;i++) {
if (recSize != n)
memmove((char*)data,(char*)data+recSize*4,(n-recSize)*4);
attemptNoDie(
readWholeBlock(device,(char*)data+n*4-recSize*4, recSize*4),
"reading from soundcard", true);
}
}
return 0;
}
#else
// generic dummy implementation
#include "syna.h"
int getNextFragment(void) {
return 0;
}
void openSound(SoundSource source, int inFrequency, const char *dspName,
char *mixerName)
{
}
void closeSound()
{
}
#endif // linux || svr4