summaryrefslogtreecommitdiffstats
path: root/kscd/kscdmagic/sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kscd/kscdmagic/sound.cpp')
-rw-r--r--kscd/kscdmagic/sound.cpp252
1 files changed, 252 insertions, 0 deletions
diff --git a/kscd/kscdmagic/sound.cpp b/kscd/kscdmagic/sound.cpp
new file mode 100644
index 00000000..0bcb8d8d
--- /dev/null
+++ b/kscd/kscdmagic/sound.cpp
@@ -0,0 +1,252 @@
+/* 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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
+