Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

SID_linux.i

Go to the documentation of this file.
00001 /*
00002  *  SID_linux.i - 6581 emulation, Linux specific stuff
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
00005  *  Linux sound stuff by Bernd Schmidt
00006  */
00007 
00008 #include <unistd.h>
00009 #include <fcntl.h>
00010 #include <sys/ioctl.h>
00011 #include <linux/soundcard.h>
00012 
00013 #include "VIC.h"
00014 
00015 //#define PCM_DUMP
00016 
00017 /*
00018  *  Initialization
00019  */
00020 
00021 void DigitalRenderer::init_sound(void)
00022 {
00023     int tmp;
00024     int rate;
00025     int dspbits;
00026     unsigned long formats;
00027 
00028     ready = false;
00029     devfd = open("/dev/dsp", O_WRONLY);
00030     
00031     if (devfd < 0)
00032                 {
00033                 printf("WARNING! could not open /dev/dsp due to %d\n", devfd);
00034                 return;
00035                 }
00036 
00037     ioctl (devfd, SNDCTL_DSP_GETFMTS, &formats);
00038     
00039     /*
00040      * Buffer size: 2^9 == 512 bytes. Note that too large buffers will not work
00041      * very well: The speed of the C64 is slowed down to an average speed of 
00042      * 100% by the blocking write() call in EmulateLine(). If you use a buffer 
00043      * of, say 4096 bytes, that will happen only about every 4 frames, which
00044      * means that the emulation runs much faster in some frames, and much
00045      * slower in others.
00046      * On really fast machines, it might make sense to use an even smaller
00047      * buffer size.
00048      */
00049     tmp = 0x00040009;
00050     ioctl (devfd, SNDCTL_DSP_SETFRAGMENT, &tmp);
00051     ioctl (devfd, SNDCTL_DSP_GETBLKSIZE, &sndbufsize);
00052     dspbits = 16;
00053     ioctl(devfd, SNDCTL_DSP_SAMPLESIZE, &dspbits);
00054     ioctl(devfd, SOUND_PCM_READ_BITS, &dspbits);
00055     if (dspbits != 16)
00056         return;
00057     
00058     tmp = 0;
00059     ioctl(devfd, SNDCTL_DSP_STEREO, &tmp);
00060     
00061     rate = 44100;
00062     ioctl(devfd, SNDCTL_DSP_SPEED, &rate);
00063     ioctl(devfd, SOUND_PCM_READ_RATE, &rate);
00064     if (rate < 43000 || rate > 45000)
00065         return;
00066 
00067     if (!(formats & AFMT_S16_LE))
00068         return;
00069             
00070     sound_buffer = new int16[sndbufsize];
00071     ready = true;
00072 }
00073 
00074 
00075 /*
00076  *  Destructor
00077  */
00078 
00079 DigitalRenderer::~DigitalRenderer()
00080 {
00081     if (devfd >= 0)
00082         close(devfd);
00083 }
00084 
00085 
00086 /*
00087  *  Pause sound output
00088  */
00089 
00090 void DigitalRenderer::Pause(void)
00091 {
00092 }
00093 
00094 
00095 /*
00096  * Resume sound output
00097  */
00098 
00099 void DigitalRenderer::Resume(void)
00100 {
00101 }
00102 
00103 
00104 /*
00105  * Fill buffer, sample volume (for sampled voice)
00106  */
00107 
00108 void DigitalRenderer::EmulateLine(void)
00109 {
00110     static int divisor = 0;
00111     static int to_output = 0;
00112     static int buffer_pos = 0;
00113 
00114     if (!ready)
00115         return;
00116 
00117         sample_buf[sample_in_ptr] = volume;
00118         sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
00119 
00120     /*
00121      * Now see how many samples have to be added for this line
00122      */
00123     divisor += SAMPLE_FREQ;
00124     while (divisor >= 0)
00125         divisor -= TOTAL_RASTERS*SCREEN_FREQ, to_output++;
00126 
00127     /*
00128      * Calculate the sound data only when we have enough to fill
00129      * the buffer entirely.
00130      */
00131     if ((buffer_pos + to_output) >= sndbufsize) {
00132         int datalen = sndbufsize - buffer_pos;
00133         to_output -= datalen;
00134         calc_buffer(sound_buffer + buffer_pos, datalen*2);
00135 
00136 #ifdef PCM_DUMP
00137 
00138     int fd = open("/tmp/frodo_pcm.dat", O_WRONLY | O_CREAT | O_APPEND);
00139         if(fd>=0)
00140                 write(fd, sound_buffer, sndbufsize*2);
00141         close(fd);
00142         
00143 #else // PCM_DUMP
00144 
00145         write(devfd, sound_buffer, sndbufsize*2);
00146 
00147 #endif // PCM_DUMP
00148 
00149 
00150         buffer_pos = 0;
00151     }    
00152 }

Generated on Tue Feb 8 04:08:12 2005 for E32frodo by doxygen 1.3.3