This is smsAnal.c in view mode; [Download] [Up]
/* * main program for smsAnal * */ #include "../sms.h" #include "smsAnal.h" char pChTextString[1024]; #define USAGE "Usage: smsAnal [-d debugMode][-f format][-q soundType][-x analysisDirection][-s windowSize][-i windowType][-r frameRate][-j highestFreq][-k minPeakMag][-y refHarmonic][-u defaultFund][-l lowestFund][-h highestFund][-m minRefHarmMag][-z refHarmMagDiffFromMax][-n nGuides][-p nTrajectories][-v freqDeviation][-t peakContToGuide][-o fundContToGuide][-g cleanTraj][-a minTrajLength][-b maxSleepingTime][-e stochasticType][-c nStocCoeff] <inputSoundFile> <outputSmsFile>" /* function to compute the SMS representation from a sound file * * SNDSoundStruct *pSoundHeader; pointer to input sound file * SMSHeader *pSmsHeader; pointer to output SMS file * ANAL_PARAMS analParams; analysis parameters */ static int ComputeSms (SNDSoundStruct *pSoundHeader, SMSHeader *pSmsHeader, ANAL_PARAMS analParams) { short *pSoundData = (short *) ((char *) pSoundHeader + pSoundHeader->dataLocation); int nSoundSamples = pSoundHeader->dataSize / sizeof(short); char *pData = (char *) pSmsHeader->pChDataRecords; SMS_DATA smsData; int iStatus = 0, iSample = 0, sizeNewData = 0, iNextSizeRead = 0, iDoAnalysis = 1, iRecord = 0; iNextSizeRead = (analParams.iDefaultSizeWindow + 1) / 2.0; if (analParams.iAnalysisDirection == REVERSE) { iSample = nSoundSamples; pData += (pSmsHeader->nRecords - 1) * pSmsHeader->iRecordBSize; } while(iDoAnalysis > 0) { if (analParams.iAnalysisDirection == REVERSE) { if ((iSample - iNextSizeRead) >= 0) sizeNewData = iNextSizeRead; else sizeNewData = iSample; iSample -= sizeNewData; } else { iSample += sizeNewData; if((iSample + iNextSizeRead) < nSoundSamples) sizeNewData = iNextSizeRead; else sizeNewData = nSoundSamples - iSample; } if (setSmsRecord (pSmsHeader, pData, &smsData) < 0) { fprintf(stderr, "error: not enough memory for SMS file\n"); fprintf(stderr, " iRecord = %d, nRecords %d\n", iRecord, pSmsHeader->nRecords); break; } iStatus = SmsAnalysis (&pSoundData[iSample], sizeNewData, &smsData, analParams, &iNextSizeRead); if (iStatus == 1) { if (analParams.iAnalysisDirection == REVERSE) pData -= pSmsHeader->iRecordBSize; else pData += pSmsHeader->iRecordBSize; if (iRecord % 10 == 0) fprintf (stderr,"%.2f ", iRecord / (float) pSmsHeader->iFrameRate); iRecord++; } else if (iStatus == -1) { iDoAnalysis = 0; pSmsHeader->nRecords = iRecord; } } pSmsHeader->fResidualPerc = FResidualPerc / iRecord; return (1); } /* function to initialize the input command arguments * * ARGUMENTS *pArguments; command arguments */ static int InitArguments (ARGUMENTS *pArguments) { pArguments->iDebugMode = 0; pArguments->iFormat = FORMAT_HARMONIC; pArguments->iSoundType = TYPE_MELODY; pArguments->iAnalysisDirection = DIRECT; pArguments->fWindowSize = 3.5; pArguments->iWindowType = BLACKMAN_HARRIS_70; pArguments->iFrameRate = 400; pArguments->fHighestFreq = 12000.; pArguments->fMinPeakMag = 0; pArguments->fFreqDeviation = .45; pArguments->iRefHarmonic = 1; pArguments->fMinRefHarmMag = 30; pArguments->fRefHarmMagDiffFromMax = 30; pArguments->fDefaultFund = 100; pArguments->fLowestFund = 50; pArguments->fHighestFund = 1000; pArguments->nGuides = 100; pArguments->nTrajectories = 60; pArguments->fPeakContToGuide = .4; pArguments->fFundContToGuide = .5; pArguments->iCleanTraj = 1; pArguments->fMinTrajLength = .1; pArguments->fMaxSleepingTime = .1; pArguments->iStochasticType = STOC_MAG_ENV_TYPE; pArguments->nStochasticCoeff = 16; return (1); } /* save the arguments as a string in the header of the SMS file * * ARGUMENTS arguments; user arguments */ static int SaveArguments (ARGUMENTS arguments) { sprintf (pChTextString, "format %d, soundType %d, analysisDirection %d, windowSize %.2f, windowType %d, frameRate %d, highestFreq %.2f, minPeakMag %.2f, refHarmonic %d, minRefHarmMag %.2f, refHarmMagDiffFromMax %.2f, defaultFund %.2f, lowestFund %.2f, highestFund %.2f, nGuides %d, nTrajectories %d, freqDeviation %.2f, peakContToGuide %.2f, fundContToGuide %.2f, cleantTraj %d, minTrajLength %.2f, maxSleepingTime %.2f, stochasticType %d, nStocCoeff %d \n", arguments.iFormat, arguments.iSoundType, arguments.iAnalysisDirection, arguments.fWindowSize, arguments.iWindowType, arguments.iFrameRate, arguments.fHighestFreq, arguments.fMinPeakMag, arguments.iRefHarmonic, arguments.fMinRefHarmMag, arguments.fRefHarmMagDiffFromMax, arguments.fDefaultFund, arguments.fLowestFund, arguments.fHighestFund, arguments.nGuides, arguments.nTrajectories, arguments.fFreqDeviation, arguments.fPeakContToGuide, arguments.fFundContToGuide, arguments.iCleanTraj, arguments.fMinTrajLength, arguments.fMaxSleepingTime, arguments.iStochasticType, arguments.nStochasticCoeff); return (1); } /* function to compute the record size from the command arguments * * ARGUMENTS *pArguments; pointer to command arguments */ static int computeRecordBSize (ARGUMENTS *pArguments) { int iSize = 0, nGain = 1, nComp = 2; if (pArguments->iStochasticType == STOC_NONE) nGain = 0; if (pArguments->iFormat == FORMAT_HARMONIC_WITH_PHASE || pArguments->iFormat == FORMAT_INHARMONIC_WITH_PHASE) nComp = 3; iSize = sizeof (float) * (nComp * pArguments->nTrajectories + pArguments->nStochasticCoeff + nGain); return (iSize); } /* function to get the user arguments * * char *argv[]; command line * int argc; number of command arguments * ARGUMENTS *pArguments; command arguments */ static int GetArguments (char *argv[], int argc, ARGUMENTS *pArguments) { int i; float frameRateOrOverlapFactor = 0; for (i=1; i<argc-2; i++) { if (*(argv[i]++) == '-') { switch (*(argv[i]++)) { case 'd': if (sscanf(argv[i],"%d", &pArguments->iDebugMode) < 0) quit("Invalid debug mode"); break; case 'f': if (sscanf(argv[i],"%d", &pArguments->iFormat) < 1) quit("Invalid format"); break; case 'q': if (sscanf(argv[i],"%d", &pArguments->iSoundType) < 0) quit("Invalid sound type"); break; case 'x': if (sscanf(argv[i],"%d", &pArguments->iAnalysisDirection) < 0) quit("Invalid value for analysis direction"); break; case 'i': if (sscanf(argv[i],"%d", &pArguments->iWindowType) < 0) quit("Invalid value for window type"); break; case 's': if (sscanf(argv[i],"%f", &pArguments->fWindowSize) < 1) quit("Invalid window size"); break; case 'r': sscanf(argv[i],"%f", &frameRateOrOverlapFactor); break; case 'j': if (sscanf(argv[i],"%f", &pArguments->fHighestFreq) < 0) quit("Invalid highestFreq"); break; case 'k': if (sscanf(argv[i],"%f", &pArguments->fMinPeakMag) < 0) quit("Invalid minimum peak magnitude"); break; case 'y': if (sscanf(argv[i],"%d", &pArguments->iRefHarmonic) < 1) quit("Invalid reference harmonic"); break; case 'm': if (sscanf(argv[i],"%f", &pArguments->fMinRefHarmMag) < 0) quit("Invalid minimum fundamental magnitude"); break; case 'z': if (sscanf(argv[i],"%f", &pArguments->fRefHarmMagDiffFromMax) < 0) quit("Invalid maximum fundamental magnitude difference \ from maximum peak"); break; case 'l': if (sscanf(argv[i],"%f", &pArguments->fLowestFund) < 1) quit("Invalid lowest fundamental"); break; case 'h': if (sscanf(argv[i],"%f", &pArguments->fHighestFund) < 1) quit("Invalid highest fundamental"); break; case 'u': if (sscanf(argv[i],"%f", &pArguments->fDefaultFund) < 1) quit("Invalid default fundamental"); break; case 'n': if (sscanf(argv[i],"%d", &pArguments->nGuides) < 1) quit("Invalid number of guides"); break; case 'p': if (sscanf(argv[i],"%d", &pArguments->nTrajectories) < 1) quit("Invalid number of trajectories"); break; case 'v': if (sscanf(argv[i],"%f", &pArguments->fFreqDeviation) < 0) quit("Invalid frequency deviation"); break; case 't': if (sscanf(argv[i],"%f", &pArguments->fPeakContToGuide) < 0) quit("Invalid peak contribution to guide"); break; case 'o': if (sscanf(argv[i],"%f", &pArguments->fFundContToGuide) < 0) quit("Invalid fundamental contribution to guide"); break; case 'g': if (sscanf(argv[i],"%d", &pArguments->iCleanTraj) < 0) quit("Invalid value for CleanTraj"); break; case 'a': if (sscanf(argv[i],"%f", &pArguments->fMinTrajLength) < 0) quit("Invalid minimum trajectory length"); break; case 'b': if (sscanf(argv[i],"%f", &pArguments->fMaxSleepingTime) < 0) quit("Invalid minimum sleeping time"); break; case 'c': if (sscanf(argv[i],"%d", &pArguments->nStochasticCoeff) < 1) quit("Invalid number of coefficients"); break; case 'e': if (sscanf(argv[i],"%d", &pArguments->iStochasticType) < 1) quit("Invalid stochastic type"); break; default: quit(USAGE); } } } if (frameRateOrOverlapFactor > 0.0) pArguments->iFrameRate = frameRateOrOverlapFactor; else if (frameRateOrOverlapFactor < 0.0) { /* -overlapFactor specified */ /* overlap ratio K = windowSize * frameRate / defaultFund = w * r / u => r = K * u / w */ pArguments->iFrameRate = (int) ((-frameRateOrOverlapFactor) * pArguments->fDefaultFund / pArguments->fWindowSize); printf("Frame rate = %d\n", pArguments->iFrameRate); } return (1); } /* function to fill SMS header of the output file * * SMSHeader *pSmsHeader; pointer to SMS header * int iRecordBSize; size in bytes of an output record * int nRecords; number of records in output file * ARGUMENTS arguments; user arguments */ static int FillSmsHeader (SMSHeader *pSmsHeader, int iRecordBSize, int nRecords, ARGUMENTS arguments) { initSmsHeader(pSmsHeader); pSmsHeader->iRecordBSize = iRecordBSize; pSmsHeader->nRecords = nRecords; pSmsHeader->iFormat = arguments.iFormat; pSmsHeader->iFrameRate = arguments.iFrameRate; pSmsHeader->iStochasticType = arguments.iStochasticType; pSmsHeader->nTrajectories = arguments.nTrajectories; pSmsHeader->nStochasticCoeff = arguments.nStochasticCoeff; pSmsHeader->pChDataRecords = (char *)pSmsHeader + pSmsHeader->iHeadBSize; pSmsHeader->fOriginalSRate = FSamplingRate; SaveArguments (arguments); pSmsHeader->nTextCharacters = strlen (pChTextString) + 1; pSmsHeader->pChTextCharacters = (char *) pChTextString; return (1); } /* function to fill the analysis parameters from the user arguments * * ARGUMENTS arguments; user arguments * ANAL_PARAMS *pAnalParams; analysis parameters * SNDSoundStruct *pSoundHeader; pointer to header of input sound * int iHopSize; hop size of analysis frame */ static int FillAnalParams (ARGUMENTS arguments, ANAL_PARAMS *pAnalParams, SNDSoundStruct *pSoundHeader, int iHopSize) { /* fill analysis parameters structure */ pAnalParams->iDebugMode = arguments.iDebugMode; pAnalParams->iFormat = arguments.iFormat; pAnalParams->iSoundType = arguments.iSoundType; pAnalParams->iAnalysisDirection = arguments.iAnalysisDirection; pAnalParams->iSizeSound = pSoundHeader->dataSize / sizeof(short); pAnalParams->iWindowType = arguments.iWindowType; FSamplingRate = pAnalParams->fSamplingRate = pSoundHeader->samplingRate; FHalfSamplingRate = FSamplingRate / 2.0; pAnalParams->fSizeWindow = arguments.fWindowSize; pAnalParams->iDefaultSizeWindow = (int)((pAnalParams->fSamplingRate / arguments.fDefaultFund) * pAnalParams->fSizeWindow / 2) * 2 + 1; /* odd length */ pAnalParams->sizeHop = iHopSize; pAnalParams->fHighestFreq = arguments.fHighestFreq; pAnalParams->fMinPeakMag = arguments.fMinPeakMag; pAnalParams->iStochasticType = arguments.iStochasticType; pAnalParams->fLowestFundamental = arguments.fLowestFund; pAnalParams->fHighestFundamental = arguments.fHighestFund; pAnalParams->fDefaultFundamental = arguments.fDefaultFund; pAnalParams->fPeakContToGuide = arguments.fPeakContToGuide; pAnalParams->fFundContToGuide = arguments.fFundContToGuide; pAnalParams->fFreqDeviation = arguments.fFreqDeviation; pAnalParams->nGuides = MAX (arguments.nGuides, arguments.nTrajectories); pAnalParams->iCleanTraj = arguments.iCleanTraj; pAnalParams->fMinRefHarmMag = arguments.fMinRefHarmMag; pAnalParams->fRefHarmMagDiffFromMax = arguments.fRefHarmMagDiffFromMax; pAnalParams->iRefHarmonic = arguments.iRefHarmonic; pAnalParams->iMinTrajLength = arguments.fMinTrajLength * arguments.iFrameRate; pAnalParams->iMaxSleepingTime = arguments.fMaxSleepingTime * arguments.iFrameRate; MaxDelayFrames = MAX(pAnalParams->iMinTrajLength, pAnalParams->iMaxSleepingTime) + 2 + DELAY_FRAMES; FResidualPerc = 0; return (1); } /* main of the program * */ void main (int argc, char *argv[]) { char *pChInputSoundFile = NULL, *pChOutputSmsFile = NULL, *pChProgramName; int iRecordBSize, iHeadBSize, iDataBSize, iHopSize, nRecords, iError; ARGUMENTS arguments; SNDSoundStruct *pSoundHeader; SMSHeader *pSmsHeader; ANAL_PARAMS analParams; /* initialize arguments */ InitArguments (&arguments); pChProgramName = argv[0]; /* get user arguments */ if (argc > 3) GetArguments (argv, argc, &arguments); else if (argc < 2) quit(USAGE); pChInputSoundFile = argv[argc-2]; pChOutputSmsFile = argv[argc-1]; /* Read sound file */ if (iError = SNDReadSoundfile (pChInputSoundFile, &pSoundHeader)) { printf("%s: sound error: %s on %s\n", pChProgramName, SNDSoundError(iError), pChInputSoundFile); exit(1); } /* Abort if unsupported format */ if (pSoundHeader->dataFormat != SND_FORMAT_LINEAR_16) { fprintf (stderr, "%s: unsupported sound format: %d\n", pChProgramName, pSoundHeader->dataFormat); exit(1); } /* Abort if multi-channel sound */ if (pSoundHeader->channelCount > 1) { fprintf (stderr,"%s: multi-channel sound not supported", pChProgramName); exit(1); } /* check default fundamental */ if (arguments.fDefaultFund < arguments.fLowestFund) { arguments.fDefaultFund = arguments.fLowestFund; fprintf (stderr,"fDefaultFundamental set to %f \n", arguments.fDefaultFund); } if (arguments.fDefaultFund > arguments.fHighestFund) { arguments.fDefaultFund = arguments.fHighestFund; fprintf (stderr,"fDefaultFundamental set to %f \n", arguments.fDefaultFund); } /* check if no stochastic component */ if(arguments.iStochasticType == STOC_NONE) arguments.nStochasticCoeff = 0; iRecordBSize = computeRecordBSize (&arguments); iHopSize = (int)(pSoundHeader->samplingRate / (float) arguments.iFrameRate); nRecords = 3 + pSoundHeader->dataSize / (float) (sizeof(short) * iHopSize); iHeadBSize = sizeof(SMSHeader); iDataBSize = iRecordBSize * nRecords; /* allocate virtual memory for SMS file */ if ((pSmsHeader = (SMSHeader *) malloc ((size_t)(iHeadBSize+iDataBSize))) == NULL) quit ("error allocating memory for SMS file"); FillAnalParams (arguments, &analParams, pSoundHeader, iHopSize); FillSmsHeader (pSmsHeader, iRecordBSize, nRecords, arguments); if (analParams.iDebugMode == DEBUG_SYNC) createDebugFile (analParams); if (analParams.iDebugMode == DEBUG_RESIDUAL) createResidualFile (analParams); ComputeSms (pSoundHeader, pSmsHeader, analParams); writeSmsFile (pChOutputSmsFile, pSmsHeader); if (analParams.iDebugMode == DEBUG_RESIDUAL) writeResidualFile (); if (analParams.iDebugMode == DEBUG_SYNC) writeDebugFile (); SNDFree (pSoundHeader); free (pSmsHeader); exit (0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.