Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

SaveSrv.cc

Go to the documentation of this file.
00001 /*
00002 
00003     Save server
00004     Copyright (C) 2001-2002 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 */
00021 
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <signal.h>
00026 #include <limits.h>
00027 #include <errno.h>
00028 #include <time.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 #include <fcntl.h>
00032 #include <sched.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 
00036 #include "SockClie.hh"
00037 
00038 #include "SaveSrv.hh"
00039 
00040 
00041 static bool bDaemon = false;
00042 static const char *cpFileExt[] = { "wav", "aiff", "flac" };
00043 static const char cpFLACMarker[] = "fLaC";
00044 clSaveSrv SaveSrv;
00045 
00046 void SigHandler (int iSigNum)
00047 {
00048     switch (iSigNum)
00049     {
00050         case SIGINT:
00051             SaveSrv.Log.Add('#', "Received SIGINT, terminating...");
00052             SaveSrv.Stop();
00053             break;
00054         case SIGTERM:
00055             SaveSrv.Log.Add('#', "Received SIGTERM, terminating...");
00056             SaveSrv.Stop();
00057             break;
00058         case SIGSEGV:
00059             SaveSrv.Log.Add('!', "Oops, received SIGSEGV, terminating...");
00060             abort();
00061             break;
00062     }
00063 }
00064 
00065 
00066 int main (int argc, char *argv[])
00067 {
00068     bool bRealTime = false;
00069     int iArgCntr;
00070     uid_t uidCurrent;
00071     struct sched_param sSchedParam;
00072 
00073     signal(SIGPIPE, SIG_IGN);
00074     signal(SIGFPE, SIG_IGN);
00075     signal(SIGINT, SigHandler);
00076     signal(SIGTERM, SigHandler);
00077     signal(SIGSEGV, SigHandler);
00078 
00079     for (iArgCntr = 1; iArgCntr < argc; iArgCntr++)
00080     {
00081         if (strcmp(argv[iArgCntr], "--rt") == 0)
00082             bRealTime = true;
00083     }
00084 
00085     if (bRealTime)
00086     {
00087         uidCurrent = getuid();
00088         setuid(0);
00089         memset(&sSchedParam, 0x00, sizeof(sSchedParam));
00090         sSchedParam.sched_priority = sched_get_priority_min(SCHED_FIFO);
00091         sched_setscheduler(getpid(), SCHED_FIFO, &sSchedParam);
00092         setuid(uidCurrent);
00093     }
00094 
00095     return SaveSrv.Main(argc, argv);
00096 }
00097 
00098 
00099 #ifdef USE_FLAC
00100 
00101 FLAC__StreamEncoderWriteStatus WrapFLACWrite (
00102     const FLAC__StreamEncoder *spFLACEnc, const FLAC__byte cpBuffer[], 
00103     unsigned uiBytes, unsigned uiSamples, unsigned uiCurrFrame,
00104     void *vpDataPtr)
00105 {
00106     clSaveSrv *SaveSrvInst = (clSaveSrv *) vpDataPtr;
00107     
00108     return SaveSrvInst->FLACWrite(spFLACEnc, cpBuffer, uiBytes, uiSamples,
00109         uiCurrFrame);
00110 }
00111 
00112 
00113 void WrapFLACMetaData (
00114     const FLAC__StreamEncoder *spFLACEnc, 
00115     const FLAC__StreamMetadata *spFLACMetaData,
00116     void *vpDataPtr)
00117 {
00118     clSaveSrv *SaveSrvInst = (clSaveSrv *) vpDataPtr;
00119 
00120     SaveSrvInst->FLACMetaData(spFLACEnc, spFLACMetaData);
00121 }
00122 
00123 #endif
00124 
00125 
00126 bool clSaveSrv::Initialize ()
00127 {
00128     char cpSndFileVer[SAVS_SNDFILE_MSGLEN + 1];
00129 
00130     Cfg.SetFileName(SD_CFGFILE);
00131     if (!Cfg.GetStr("LocalSocket", cpSockName))
00132     {
00133         Log.Add('!', "\"LocalSocket\" not found from configuration file");
00134         return false;
00135     }
00136     Cfg.SetFileName(SAVS_CFGFILE);
00137     if (!Cfg.GetStr("SavePath", cpSavePath))
00138     {
00139         Log.Add('!', "\"SavePath\" not found from configuration file");
00140         return false;
00141     }
00142     if (!Cfg.GetInt("Format", &iFormat))
00143     {
00144         Log.Add('!', "\"Format\" not found from configuration file");
00145         return false;
00146     }
00147     if (!Cfg.GetInt("Type", &iType))
00148     {
00149         Log.Add('!', "\"Type\" not found from configuration file");
00150         return false;
00151     }
00152     if (!Cfg.GetInt("Bits", &iBits))
00153     {
00154         Log.Add('!', "\"Bits\" not found from configuration file");
00155         return false;
00156     }
00157     if (!Cfg.GetInt("Dither", &iDither))
00158         iDither = 0;
00159     if (iBits != 8 && iBits != 16 && iBits != 24)
00160     {
00161         iDither = 0;
00162         Log.Add(' ', "Unsupported word length for dithering, dither disabled");
00163     }
00164     if (!Cfg.GetInt("FrameLength", &lFrameLen))
00165         lFrameLen = SAVS_DEF_FRAMELEN;
00166     if (!Cfg.GetInt("FileTime", &iFileTime))
00167         iFileTime = SAVS_DEF_FILETIME;
00168 
00169     lFrameSize = lFrameLen * sizeof(GDT);
00170     InFrame.Size(lFrameSize);
00171     if (iDither == 1)
00172     {
00173         OutFrame.Size(lFrameLen * (iBits / 8));
00174         Log.Add(' ', "Dither enabled");
00175     }
00176     else
00177     {
00178         OutFrame.Size(lFrameLen * sizeof(double));
00179         Log.Add(' ', "Dither disabled");
00180     }
00181     NoiseFrame.Size(lFrameLen * sizeof(int));
00182     #ifdef USE_FLAC
00183     FLACFrame.Size(lFrameLen * sizeof(FLAC__int32));
00184     #endif
00185 
00186     #ifdef linux
00187     int iRndH = open("/dev/urandom", O_RDONLY);
00188     if (iRndH < 0)
00189     {
00190         Log.Add('!', "Unable to access /dev/urandom", errno);
00191         return false;
00192     }
00193     if (read(iRndH, &uiRndSeed, sizeof(unsigned int)) == sizeof(unsigned int))
00194     {
00195         Log.Add(' ', "Random number generator seeded using /dev/urandom");
00196     }
00197     else
00198     {
00199         uiRndSeed = time(NULL);
00200         Log.Add('#', "Unable to read /dev/urandom, seeding with time");
00201     }
00202     close(iRndH);
00203     #else
00204     uiRndSeed = time(NULL);
00205     #endif
00206 
00207     int iRandVal;
00208     int *ipRndPtr = NoiseFrame;
00209     #if (defined(linux) || defined(BSDSYS))
00210     srandom(uiRndSeed);
00211     #else
00212     srand(uiRndSeed);
00213     #endif
00214     for (long lRndCntr = 0; lRndCntr < lFrameLen; lRndCntr++)
00215     {
00216         #if (defined(linux) || defined(BSDSYS))
00217         iRandVal = random();
00218         #else
00219         iRandVal = rand();
00220         #endif
00221         ipRndPtr[lRndCntr] = (iRandVal & 0x7fffffff);
00222     }
00223     #ifdef USE_MERSENNE_TWISTER
00224     MTR = new MTRand(uiRndSeed);
00225     Log.Add(' ', "Using Mersenne Twister as PRNG");
00226     #endif
00227 
00228     iFileTime *= 60;
00229 
00230     sf_command(NULL, SFC_GET_LIB_VERSION, cpSndFileVer, SAVS_SNDFILE_MSGLEN);
00231     Log.Add(' ', cpSndFileVer);
00232     return true;
00233 }
00234 
00235 
00236 bool clSaveSrv::ConnectStream ()
00237 {
00238     int iSockH;
00239     char cpLogEntry[SAVS_LOGENTRY_SIZE + 1];
00240     stRawDataReq sDataReq;
00241     clSockClie SClient;
00242 
00243     iSockH = SClient.Connect(cpSockName);
00244     if (iSockH < 0) 
00245     {
00246         Log.Add('!', "clSockClie::Connect() failed", SClient.GetErrno());
00247         return false;
00248     }
00249     SOp.SetHandle(iSockH);
00250     if (SOp.ReadN(&sDataHdr, sizeof(sDataHdr)) != sizeof(sDataHdr))
00251     {
00252         Log.Add('!', "clSockOp::ReadN() failed", SOp.GetErrno());
00253         return false;
00254     }
00255     sDataReq.iChannel = -1;
00256     if (SOp.WriteN(&sDataReq, sizeof(sDataReq)) != sizeof(sDataReq))
00257     {
00258         Log.Add('!', "clSockOp::WriteN() failed", SOp.GetErrno());
00259         return false;
00260     }
00261     sprintf(cpLogEntry, "Stream ch %i fs %g", sDataHdr.iChannels,
00262         sDataHdr.dSampleRate);
00263     Log.Add(' ', cpLogEntry);
00264     return true;
00265 }
00266 
00267 
00268 bool clSaveSrv::CreateFile ()
00269 {
00270     char cpFileName[_POSIX_PATH_MAX + 1];
00271     SF_INFO sSndInfo;
00272 
00273     if (spSndFile != NULL) sf_close(spSndFile);
00274 
00275     CreateFileName(cpFileName);
00276 
00277     memset(&sSndInfo, 0x00, sizeof(sSndInfo));
00278     sSndInfo.samplerate = (int) (sDataHdr.dSampleRate + 0.5);
00279     sSndInfo.channels = sDataHdr.iChannels;
00280     switch (iFormat)
00281     {
00282         case SAVS_FORMAT_WAV:
00283             sSndInfo.format = SF_FORMAT_WAV;
00284             break;
00285         case SAVS_FORMAT_AIFF:
00286             sSndInfo.format = SF_FORMAT_AIFF;
00287             break;
00288         default:
00289             iFormat = SAVS_FORMAT_WAV;
00290             sSndInfo.format = (SF_FORMAT_WAV|SF_FORMAT_PCM_16);
00291     }
00292     switch (iType)
00293     {
00294         case SAVS_TYPE_PCM:
00295             switch (iBits)
00296             {
00297                 case 8:
00298                     sSndInfo.format |= SF_FORMAT_PCM_U8;
00299                     break;
00300                 case 16:
00301                     sSndInfo.format |= SF_FORMAT_PCM_16;
00302                     break;
00303                 case 24:
00304                     sSndInfo.format |= SF_FORMAT_PCM_24;
00305                     break;
00306                 case 32:
00307                     sSndInfo.format |= SF_FORMAT_PCM_32;
00308                     break;
00309             }
00310             break;
00311         case SAVS_TYPE_FLOAT:
00312             sSndInfo.format |= SF_FORMAT_FLOAT;
00313             break;
00314         case SAVS_TYPE_ADPCM:
00315             sSndInfo.format |= SF_FORMAT_IMA_ADPCM;
00316             break;
00317         case SAVS_TYPE_MSADPCM:
00318             sSndInfo.format |= SF_FORMAT_MS_ADPCM;
00319             break;
00320         default:
00321             sSndInfo.format |= SF_FORMAT_FLOAT;
00322     }
00323     sSndInfo.format |= SF_ENDIAN_FILE;
00324     if (!sf_format_check(&sSndInfo))
00325     {
00326         Log.Add('!', "Invalid file format");
00327         return false;
00328     }
00329     spSndFile = sf_open(cpFileName, SFM_WRITE, &sSndInfo);
00330     if (spSndFile == NULL)
00331     {
00332         Log.Add('!', "File open failed");
00333         return false;
00334     }
00335     if (!sf_command(spSndFile, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE))
00336     {
00337         // ignore results for now, bug in libsndfile, wrong return value
00338         /*Log.Add('!', "Setting normalization behaviour failed");
00339         return false;*/
00340     }
00341     if (iDither > 1)
00342     {
00343         if (!sf_command(spSndFile, SFC_SET_ADD_DITHER_ON_WRITE, NULL, SF_TRUE))
00344         {
00345             Log.Add('#', "Warning, failed to enable dithering");
00346         }
00347     }
00348     Log.Add('+', cpFileName);
00349     return true;
00350 }
00351 
00352 
00353 bool clSaveSrv::CreateFile2 ()
00354 {
00355     #ifdef USE_FLAC
00356     int iMaxLPCOrder;
00357     int iMinRiceOrder;
00358     int iMaxRiceOrder;
00359     char cpFileName[_POSIX_PATH_MAX + 1];
00360     FLAC__StreamEncoderState iEncState;
00361     
00362     if (spFLACEnc != NULL && iFileH >= 0) 
00363     {
00364         FLAC__stream_encoder_finish(spFLACEnc);
00365         close(iFileH);
00366     }
00367 
00368     if (!Cfg.GetInt("FLACMaxLPCOrder", &iMaxLPCOrder))
00369         iMaxLPCOrder = 0;
00370     if (iMaxLPCOrder > (int) FLAC__MAX_LPC_ORDER)
00371         iMaxLPCOrder = FLAC__MAX_LPC_ORDER;
00372     if (!Cfg.GetInt("FLACMinRiceOrder", &iMinRiceOrder))
00373         iMinRiceOrder = 0;
00374     if (!Cfg.GetInt("FLACMaxRiceOrder", &iMaxRiceOrder))
00375         iMaxRiceOrder = 0;
00376     if (iMaxRiceOrder > (int) FLAC__MAX_RICE_PARTITION_ORDER)
00377         iMaxRiceOrder = FLAC__MAX_RICE_PARTITION_ORDER;
00378 
00379     CreateFileName(cpFileName);
00380     
00381     iFileH = open(cpFileName, O_WRONLY|O_CREAT, 
00382         S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
00383     if (iFileH < 0)
00384     {
00385         Log.Add('!', "File open failed");
00386         return false;
00387     }
00388 
00389     if (spFLACEnc == NULL)
00390     {
00391         spFLACEnc = FLAC__stream_encoder_new();
00392         if (spFLACEnc == NULL)
00393         {
00394             Log.Add('!', "FLAC constructor failed");
00395             return false;
00396         }
00397     }
00398     FLAC__stream_encoder_set_streamable_subset(spFLACEnc,
00399         1);
00400     FLAC__stream_encoder_set_do_mid_side_stereo(spFLACEnc,
00401         0);
00402     FLAC__stream_encoder_set_loose_mid_side_stereo(spFLACEnc,
00403         0);
00404     FLAC__stream_encoder_set_channels(spFLACEnc,
00405         sDataHdr.iChannels);
00406     FLAC__stream_encoder_set_bits_per_sample(spFLACEnc,
00407         iBits);
00408     FLAC__stream_encoder_set_sample_rate(spFLACEnc,
00409         (int) (sDataHdr.dSampleRate + 0.5));
00410     FLAC__stream_encoder_set_blocksize(spFLACEnc,
00411         lFrameLen);
00412     FLAC__stream_encoder_set_max_lpc_order(spFLACEnc,
00413         iMaxLPCOrder);
00414     FLAC__stream_encoder_set_qlp_coeff_precision(spFLACEnc,
00415         0);
00416     FLAC__stream_encoder_set_do_qlp_coeff_prec_search(spFLACEnc,
00417         0);
00418     FLAC__stream_encoder_set_do_escape_coding(spFLACEnc,
00419         1);  // non-default
00420     FLAC__stream_encoder_set_do_exhaustive_model_search(spFLACEnc,
00421         1);  // non-default
00422     FLAC__stream_encoder_set_min_residual_partition_order(spFLACEnc,
00423         iMinRiceOrder);
00424     FLAC__stream_encoder_set_max_residual_partition_order(spFLACEnc,
00425         iMaxRiceOrder);
00426     FLAC__stream_encoder_set_rice_parameter_search_dist(spFLACEnc,
00427         0);
00428     /*FLAC__stream_encoder_set_total_samples_estimate(spFLACEnc,
00429         sDataHdr.dSampleRate * iFileTime * 60);*/
00430     FLAC__stream_encoder_set_total_samples_estimate(spFLACEnc,
00431         0);
00432     FLAC__stream_encoder_set_metadata(spFLACEnc, 
00433         NULL, 0);
00434     FLAC__stream_encoder_set_write_callback(spFLACEnc,
00435         WrapFLACWrite);
00436     FLAC__stream_encoder_set_metadata_callback(spFLACEnc,
00437         WrapFLACMetaData);
00438     FLAC__stream_encoder_set_client_data(spFLACEnc,
00439         (void *) this);
00440 
00441     iEncState = FLAC__stream_encoder_init(spFLACEnc);
00442     if (iEncState != FLAC__STREAM_ENCODER_OK)
00443     {
00444         Log.Add('!', FLAC__StreamEncoderStateString[iEncState]);
00445         return false;
00446     }
00447     
00448     Log.Add('+', cpFileName);
00449     return true;
00450     #else
00451     return false;
00452     #endif
00453 }
00454 
00455 
00456 void clSaveSrv::CreateFileName (char *cpFileName)
00457 {
00458     int iFileNumber;
00459     char cpTime[SAVS_TIMELEN + 1];
00460     time_t ttTime;
00461 
00462     ttTime = time(NULL);
00463     ttFileStarted = ttTime - ttTime % iFileTime;
00464     strftime(cpTime, SAVS_TIMELEN + 1, "%d%m%Y%H%M", localtime(&ttFileStarted));
00465     iFileNumber = 0;
00466     do
00467     {
00468         sprintf(cpFileName, "%s%s-%i.%s", 
00469             cpSavePath, cpTime, iFileNumber, cpFileExt[iFormat]);
00470         iFileNumber++;
00471     } while(access(cpFileName, F_OK) == 0);
00472 }
00473 
00474 
00475 void clSaveSrv::ProcessLoop ()
00476 {
00477     time_t ttTime;
00478 
00479     Log.Add(' ', "Entering process loop");
00480     if (iFormat == SAVS_FORMAT_WAV ||
00481         iFormat == SAVS_FORMAT_AIFF)
00482     {
00483         if (!CreateFile()) Stop();
00484     }
00485     else if (iFormat == SAVS_FORMAT_FLAC)
00486     {
00487         if (!CreateFile2()) Stop();
00488     }
00489     while (bRun)
00490     {
00491         if (access(SAVS_SHUTDOWNFILE, F_OK) == 0)
00492         {
00493             unlink(SAVS_SHUTDOWNFILE);
00494             Stop();
00495             break;
00496         }
00497         if (SOp.ReadN(InFrame, lFrameSize) != lFrameSize)
00498         {
00499             Log.Add('!', "clSockOp::ReadN() error", SOp.GetErrno());
00500             break;
00501         }
00502         if (iFormat == SAVS_FORMAT_WAV || 
00503             iFormat == SAVS_FORMAT_AIFF)
00504         {
00505             if (!WriteData()) break;
00506         }
00507         else if (iFormat == SAVS_FORMAT_FLAC)
00508         {
00509             if (!WriteData2()) break;
00510         }
00511         ttTime = time(NULL);
00512         if ((ttTime - ttTime % iFileTime) > ttFileStarted)
00513         {
00514             if (iFormat == SAVS_FORMAT_WAV ||
00515                 iFormat == SAVS_FORMAT_AIFF)
00516             {
00517                 if (!CreateFile()) break;
00518             }
00519             else if (iFormat == SAVS_FORMAT_FLAC)
00520             {
00521                 if (!CreateFile2()) break;
00522             }
00523         }
00524     }
00525     Log.Add(' ', "Leaving process loop");
00526 }
00527 
00528 
00529 void clSaveSrv::Dither ()
00530 {
00531     int iSignMask;
00532     int iNoiseMask;
00533     long lSampleCntr;
00534     long lTempSample;
00535     GDT fDithScale;
00536     #ifndef USE_MERSENNE_TWISTER
00537     int *ipNoiseFrame = NoiseFrame;
00538     #endif
00539     GDT *fpInFrame = InFrame;
00540 
00541     if (iBits == 8)
00542     {
00543         fDithScale = 0x7f000000;
00544         iSignMask  = 0x00800000;
00545         iNoiseMask = 0x007fffff;
00546         unsigned char *ipOutFrame8 = OutFrame;
00547         for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00548         {
00549             #ifndef USE_MERSENNE_TWISTER
00550             int iRndVal = ipNoiseFrame[lSampleCntr];
00551             #else
00552             int iRndVal = (int) (MTR->randInt() & 0x7fffffff);
00553             #endif
00554             int iDithVal = (iRndVal & iSignMask) ?
00555                 -(iRndVal & iNoiseMask) : (iRndVal & iNoiseMask);
00556             lTempSample = 
00557                 (long) (fpInFrame[lSampleCntr] * fDithScale) + iDithVal;
00558             ipOutFrame8[lSampleCntr] = (unsigned char)
00559                 ((lTempSample >> 24) + 0x7f);
00560         }
00561     }
00562     else if (iBits == 16)
00563     {
00564         fDithScale = 0x7fff0000;
00565         iSignMask  = 0x00008000;
00566         iNoiseMask = 0x00007fff;
00567         signed short *ipOutFrame16 = OutFrame;
00568         for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00569         {
00570             #ifndef USE_MERSENNE_TWISTER
00571             int iRndVal = ipNoiseFrame[lSampleCntr];
00572             #else
00573             int iRndVal = (int) (MTR->randInt() & 0x7fffffff);
00574             #endif
00575             int iDithVal = (iRndVal & iSignMask) ?
00576                 -(iRndVal & iNoiseMask) : (iRndVal & iNoiseMask);
00577             lTempSample = 
00578                 (long) (fpInFrame[lSampleCntr] * fDithScale) + iDithVal;
00579             ipOutFrame16[lSampleCntr] = (signed short) 
00580                 (lTempSample >> 16);
00581         }
00582     }
00583     else if (iBits == 24)
00584     {
00585         fDithScale = 0x7fffff00;
00586         iSignMask  = 0x00000080;
00587         iNoiseMask = 0x0000007f;
00588         signed int *ipOutFrame24 = OutFrame;
00589         for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00590         {
00591             #ifndef USE_MERSENNE_TWISTER
00592             int iRndVal = ipNoiseFrame[lSampleCntr];
00593             #else
00594             int iRndVal = (int) (MTR->randInt() & 0x7fffffff);
00595             #endif
00596             int iDithVal = (iRndVal & iSignMask) ?
00597                 -(iRndVal & iNoiseMask) : (iRndVal & iNoiseMask);
00598             lTempSample = 
00599                 (long) (fpInFrame[lSampleCntr] * fDithScale) + iDithVal;
00600             ipOutFrame24[lSampleCntr] = (signed int)
00601                 (lTempSample >> 8);
00602         }
00603     }
00604 }
00605 
00606 
00607 bool clSaveSrv::WriteData ()
00608 {
00609     char cpSndFileError[SAVS_SNDFILE_MSGLEN + 1];
00610 
00611     if (iDither == 1)
00612     {
00613         Dither();
00614         if (iBits == 8)
00615         {
00616             if (sf_write_raw(spSndFile, OutFrame, (sf_count_t) lFrameLen) != 
00617                 (sf_count_t) lFrameLen)
00618             {
00619                 sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00620                 Log.Add('!', cpSndFileError);
00621                 return false;
00622             }
00623         }
00624         else if (iBits == 16)
00625         {
00626             if (sf_write_short(spSndFile, OutFrame, (sf_count_t) lFrameLen) != 
00627                 (sf_count_t) lFrameLen)
00628             {
00629                 sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00630                 Log.Add('!', cpSndFileError);
00631                 return false;
00632             }
00633         }
00634         else if (iBits == 24)
00635         {
00636             if (sf_write_int(spSndFile, OutFrame, (sf_count_t) lFrameLen) != 
00637                 (sf_count_t) lFrameLen)
00638             {
00639                 sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00640                 Log.Add('!', cpSndFileError);
00641                 return false;
00642             }
00643         }
00644     }
00645     else
00646     {
00647         GDT *fpInFrame = InFrame;
00648         double *dpOutFrame = OutFrame;
00649         for (long lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00650         {
00651             dpOutFrame[lSampleCntr] = fpInFrame[lSampleCntr];
00652         }
00653         if (sf_write_double(spSndFile, dpOutFrame, (sf_count_t) lFrameLen) != 
00654             (sf_count_t) lFrameLen)
00655         {
00656             sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00657             Log.Add('!', cpSndFileError);
00658             return false;
00659         }
00660     }
00661     return true;
00662 }
00663 
00664 
00665 bool clSaveSrv::WriteData2 ()
00666 {
00667     #ifdef USE_FLAC
00668     long lSampleCntr;
00669     FLAC__int32 *ipDest = FLACFrame;
00670 
00671     if (iDither == 1)
00672     {
00673         Dither();
00674     }
00675     else
00676     {
00677         float *fpInFrame = InFrame;
00678         if (iBits == 8)
00679             DSP.Convert((unsigned char *) OutFrame, fpInFrame, lFrameLen);
00680         if (iBits == 16)
00681             DSP.Convert((signed short *) OutFrame, fpInFrame, lFrameLen, false);
00682         if (iBits == 24)
00683             DSP.Convert((signed int *) OutFrame, fpInFrame, lFrameLen, true);
00684     }
00685     if (iBits == 8)
00686     {
00687         unsigned char *ipSrc = OutFrame;
00688 
00689         for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00690             ipDest[lSampleCntr] = (FLAC__int32) ipSrc[lSampleCntr] - 0x80;
00691     }
00692     else if (iBits == 16)
00693     {
00694         signed short *ipSrc = OutFrame;
00695 
00696         for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00697             ipDest[lSampleCntr] = (FLAC__int32) ipSrc[lSampleCntr];
00698     }
00699     else if (iBits == 24)
00700     {
00701         signed int *ipSrc = OutFrame;
00702 
00703         for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00704             ipDest[lSampleCntr] = 
00705                 ((FLAC__int32) ipSrc[lSampleCntr] >> 8);
00706     }
00707     if (!FLAC__stream_encoder_process_interleaved(spFLACEnc,
00708         ipDest, lFrameLen / sDataHdr.iChannels))
00709         return false;
00710     return true;
00711     #else
00712     return false;
00713     #endif
00714 }
00715 
00716 
00717 
00718 clSaveSrv::clSaveSrv ()
00719 {
00720     bRun = true;
00721     iFileH = -1;
00722     spSndFile = NULL;
00723     #ifdef USE_FLAC
00724     spFLACEnc = NULL;
00725     #endif
00726     #ifdef USE_MERSENNE_TWISTER
00727     MTR = NULL;
00728     #endif
00729     Log.Open(SAVS_LOGFILE);
00730     Log.Add('*', "Starting");
00731 }
00732 
00733 
00734 clSaveSrv::~clSaveSrv ()
00735 {
00736     #ifdef USE_MERSENNE_TWISTER
00737     if (MTR != NULL) delete MTR;
00738     #endif
00739     #ifdef USE_FLAC
00740     if (spFLACEnc != NULL) 
00741     {
00742         if (iFileH >= 0)
00743         {
00744             FLAC__stream_encoder_finish(spFLACEnc);
00745             close(iFileH);
00746         }
00747         FLAC__stream_encoder_delete(spFLACEnc);
00748     }
00749     #endif
00750     if (spSndFile != NULL) sf_close(spSndFile);
00751     Log.Add('*', "Ending");
00752 }
00753 
00754 
00755 int clSaveSrv::Main (int iArgC, char **cpArgV)
00756 {
00757     if (iArgC >= 2)
00758     {
00759         if (strcmp(cpArgV[1], "-D"))
00760         {
00761             bDaemon = true;
00762         }
00763         else if (strcmp(cpArgV[1], "--version"))
00764         {
00765             printf("%s v%i.%i.%i\n", cpArgV[0], SAVS_VERSMAJ,
00766                 SAVS_VERSMIN, SAVS_VERSPL);
00767             printf("Copyright (C) 2001-2002 Jussi Laako\n");
00768             return 0;
00769         }
00770         else if (strcmp(cpArgV[1], "--help"))
00771         {
00772             printf("%s [-D|--version|--help]\n\n", cpArgV[0]);
00773             printf("-D         start as daemon\n");
00774             printf("--version  display version information\n");
00775             printf("--help     display this help\n");
00776             return 0;
00777         }
00778     }
00779     if (bDaemon)
00780     {
00781         if (fork() != 0)
00782         {
00783             exit(0);
00784         }
00785         setsid();
00786         freopen("/dev/null", "r+", stderr);
00787         freopen("/dev/null", "r+", stdin);
00788         freopen("/dev/null", "r+", stdout);
00789     }
00790     if (!Initialize()) return 1;
00791     if (!ConnectStream()) return 2;
00792     ProcessLoop();
00793     return 0;
00794 }
00795 
00796 
00797 #ifdef USE_FLAC
00798 
00799 FLAC__StreamEncoderWriteStatus clSaveSrv::FLACWrite (
00800     const FLAC__StreamEncoder *spFLACEnc, const FLAC__byte *cpBuffer, 
00801     unsigned uiBytes, unsigned uiSamples, unsigned uiCurrFrame)
00802 {
00803     if (write(iFileH, cpBuffer, uiBytes) != (int) uiBytes)
00804         return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
00805     return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
00806 }
00807 
00808 
00809 void clSaveSrv::FLACMetaData (
00810     const FLAC__StreamEncoder *spFLACEnc, 
00811     const FLAC__StreamMetadata *spFLACMetaData)
00812 {
00813     //lseek(iFileH, 4, SEEK_SET);
00814     //write(iFileH, spFLACMetaData, sizeof(FLAC__StreamMetaData));
00815 }
00816 
00817 #endif

Generated on Sun Oct 26 19:11:22 2003 for HASAS by doxygen 1.3.3