void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent) { /* first clear everything */ memset(receiver, 0, sizeof(*receiver)); /* now copy in the parameters */ receiver->agent = agent; /* set defaults */ receiver->sFlowRcvrMaximumDatagramSize = SFL_DEFAULT_DATAGRAM_SIZE; receiver->sFlowRcvrPort = SFL_DEFAULT_COLLECTOR_PORT; #ifdef SFLOW_DO_SOCKET /* initialize the socket address */ initSocket(receiver); #endif /* preset some of the header fields */ receiver->sampleCollector.datap = receiver->sampleCollector.data; putNet32(receiver, SFLDATAGRAM_VERSION5); putAddress(receiver, &agent->myIP); putNet32(receiver, agent->subId); /* prepare to receive the first sample */ resetSampleCollector(receiver); }
/***************************************************************************** * * sfReader::FillSampleBucket * * Implementation Notes: * * The reader is being called upon for the sample data. This fills the * buffer with the amount of data specified by the *pdwSize. The actual * amount of data (in BYTES) filled is stuffed into *pdwSize in this routine. * If all data has been collected, *pdwSize is set to 0. * * If SetupToFillSampleBuckets() was never called, the variables used would * indicate that all data has already been collected. This allows * this routine to exit smoothly if called inappropriately. * * Note there are 3 sizes to consider on any read: * 1. dwThisBucketSize: The size in bytes of the bucket requested by the client. * 2. dwSampleBytesCollected: The size in bytes of the total sample data space * of this reader's SoundFont * 3. MAX_READ_SIZE: The size in bytes of the largest possible data read. * * So the algorythm tries to fill up the bucket (specified by dwThisBucketSize) * in blocks of MAX_READ_SIZE until either the bucket is full or until * the total number of bytes collected equals the total sample data space of * the SoundFont. When the latter condition is met, the SoundFont data storage * medium is closed. * ****************************************************************************** */ void sfReader:: FillSampleBucket(BYTE *pbyBucket, DWORD * pdwSize) { SHORT iReadSize; SHORT iReadSizeAct; WORD uiNdx = 0; //, uiCount; DWORD dwThisBucketSize = *pdwSize; if (dwSampleBytesCollected >= dwSampleSize) { *pdwSize = 0; return; } if ((dwSampleSize - dwSampleBytesCollected) < dwThisBucketSize) dwThisBucketSize = dwSampleSize - dwSampleBytesCollected; *pdwSize = 0; for (; dwThisBucketSize > 0; dwThisBucketSize -= iReadSizeAct, uiNdx++) { iReadSize = (dwThisBucketSize > MAX_READ_SIZE) ? MAX_READ_SIZE: (SHORT)dwThisBucketSize; iReadSizeAct = tRIFF.RIFFRead(&pbyBucket[uiNdx*MAX_READ_SIZE], iReadSize, 1); if (iReadSizeAct != 1) return; iReadSizeAct = iReadSize; #ifdef __BYTE_INCOHERENT //******************************************* // Yes, samples need to be byte-swapped too! //******************************************* for (uiCount = 0; uiCount < iReadSizeAct; uiCount +=2) { tRIFF.SwapBytes((WORD *)&pbyBucket[uiCount]); } #endif *pdwSize += iReadSize; dwSampleBytesCollected += iReadSize; if (dwSampleBytesCollected >= dwSampleSize) { resetSampleCollector(); tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; break; } } }
////////////////////////////////// // The first callable Constructor ////////////////////////////////// void sfReader::ConstructSFReader(void) { SetError(SUCCESS); /* Private members */ bySFDataLoc = SFR_NO_DATA; // Flag to indicate storage medium bySFStorageStatus = SFR_CLOSED; // Flag to indicate if storage medium is open pathName = NULL; for(INT i=0;i<CkCount;i++) // Insures we are not 'delete'-ing any data infoCkValues[i] = NULL; // which was not 'new'-ed. resetSampleCollector(); }
static void sendSample(SFLReceiver *receiver) { /* construct and send out the sample, then reset for the next one... */ SFLAgent *agent = receiver->agent; /* go back and fill in the header */ receiver->sampleCollector.datap = receiver->sampleCollector.data; putNet32(receiver, SFLDATAGRAM_VERSION5); putAddress(receiver, &agent->myIP); putNet32(receiver, agent->subId); putNet32(receiver, ++receiver->sampleCollector.packetSeqNo); putNet32(receiver, (uint32_t)((agent->now - agent->bootTime) * 1000)); putNet32(receiver, receiver->sampleCollector.numSamples); /* send */ if(agent->sendFn) (*agent->sendFn)(agent->magic, agent, receiver, (u_char *)receiver->sampleCollector.data, receiver->sampleCollector.pktlen); else { #ifdef SFLOW_DO_SOCKET /* send it myself */ if (receiver->sFlowRcvrAddress.type == SFLADDRESSTYPE_IP_V6) { uint32_t soclen = sizeof(struct sockaddr_in6); int result = sendto(agent->receiverSocket6, receiver->sampleCollector.data, receiver->sampleCollector.pktlen, 0, (struct sockaddr *)&receiver->receiver6, soclen); if(result == -1 && errno != EINTR) sfl_agent_sysError(agent, "receiver", "IPv6 socket sendto error"); if(result == 0) sfl_agent_error(agent, "receiver", "IPv6 socket sendto returned 0"); } else { uint32_t soclen = sizeof(struct sockaddr_in); int result = sendto(agent->receiverSocket4, receiver->sampleCollector.data, receiver->sampleCollector.pktlen, 0, (struct sockaddr *)&receiver->receiver4, soclen); if(result == -1 && errno != EINTR) sfl_agent_sysError(agent, "receiver", "socket sendto error"); if(result == 0) sfl_agent_error(agent, "receiver", "socket sendto returned 0"); } #endif } /* reset for the next time */ resetSampleCollector(receiver); }
static void sendSample(SFLReceiver *receiver) { /* construct and send out the sample, then reset for the next one... */ /* first fill in the header with the latest values */ /* version, agent_address and sub_agent_id were pre-set. */ u_int32_t hdrIdx = (receiver->agent->myIP.type == SFLADDRESSTYPE_IP_V6) ? 7 : 4; receiver->sampleCollector.data[hdrIdx++] = htonl(++receiver->sampleCollector.packetSeqNo); /* seq no */ receiver->sampleCollector.data[hdrIdx++] = htonl((receiver->agent->now - receiver->agent->bootTime) * 1000); /* uptime */ receiver->sampleCollector.data[hdrIdx++] = htonl(receiver->sampleCollector.numSamples); /* num samples */ /* send */ if(receiver->agent->sendFn) (*receiver->agent->sendFn)(receiver->agent->magic, receiver->agent, receiver, (u_char *)receiver->sampleCollector.data, receiver->sampleCollector.pktlen); else { #ifdef SFLOW_DO_SOCKET /* send it myself */ if (receiver->sFlowRcvrAddress.type == SFLADDRESSTYPE_IP_V6) { u_int32_t soclen = sizeof(struct sockaddr_in6); int result = sendto(receiver->agent->receiverSocket6, receiver->sampleCollector.data, receiver->sampleCollector.pktlen, 0, (struct sockaddr *)&receiver->receiver6, soclen); if(result == -1 && errno != EINTR) sfl_agent_sysError(receiver->agent, "receiver", "IPv6 socket sendto error"); if(result == 0) sfl_agent_error(receiver->agent, "receiver", "IPv6 socket sendto returned 0"); } else { u_int32_t soclen = sizeof(struct sockaddr_in); int result = sendto(receiver->agent->receiverSocket4, receiver->sampleCollector.data, receiver->sampleCollector.pktlen, 0, (struct sockaddr *)&receiver->receiver4, soclen); if(result == -1 && errno != EINTR) sfl_agent_sysError(receiver->agent, "receiver", "socket sendto error"); if(result == 0) sfl_agent_error(receiver->agent, "receiver", "socket sendto returned 0"); } #endif } /* reset for the next time */ resetSampleCollector(receiver); }
void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent) { /* first clear everything */ memset(receiver, 0, sizeof(*receiver)); /* now copy in the parameters */ receiver->agent = agent; /* set defaults */ receiver->sFlowRcvrMaximumDatagramSize = SFL_DEFAULT_DATAGRAM_SIZE; receiver->sFlowRcvrPort = SFL_DEFAULT_COLLECTOR_PORT; #ifdef SFLOW_DO_SOCKET /* initialize the socket address */ initSocket(receiver); #endif /* prepare to receive the first sample */ resetSampleCollector(receiver); }
static void sflError(SFLReceiver *receiver, char *msg) { sfl_agent_error(receiver->agent, "receiver", msg); resetSampleCollector(receiver); }
HydraClass* sfReader:: ReadSFBData (CHAR * pchReqdWaveTable) /***************************************************************************** * * Implementation Notes: * * This file reads the given SoundfontBank file into memory as a HydraClass * object. Uses the class RIFFClass object used to read up the file and * move through the various Chunks and sub chunks. It stores all the info * chunk stuff in a global infoCkValues array, and the preset data into * a hydraClass object, it sticks the names into the last SampleHdr array * of the hydrafont. * ***************************************************************************** */ { HydraClass *hf; sfVersion *fversion = NULL; CHAR *pchIROMChunk; WORD uiCount; bool bROMSamples = FALSE; if ((hf = new HydraClass) == NULL) { SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } tRIFF.Reset(); resetSampleCollector(); /* * Verify SoundFont data format */ if ( (tRIFF.GetCkID() != MAKE_ID(tRIFF.GetRIFFToken(Riff) ) && (tRIFF.GetCkFormID() != MAKE_ID(tRIFF.GetRIFFToken(Sfbk)) ))) { if(tRIFF.GetCkFormID() == MAKE_ID("SFBK")) /* all caps is a no no */ { /* accept it anyway */ /* cout<<"%ReadSFBK-I-found upcase SFBK fixing..."; */ } else { /* really was a format error */ delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } } storeInfoCks(); /* stores all present infoSub chunks in the array */ /* infoCkValues... */ fversion = (sfVersion*)(infoCkValues[Ifil]); if(fversion == NULL) { // can't set the version of our hydraClass object. ifil is a _manditory_ // info sub-chunk. We looked for "ifil" and "IFIL" (the second is illegal, // but does exist in otherwise valid banks, so we accept it as well.... SetError(SF_INVALIDBANK); #ifdef DEBUG qDebug()<<"%ReadSFBFile()-E-Bad Format, ifil (file version)" <<" info subchunk missing"; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; return NULL; } hf->SetVersion(fversion->wMajor, fversion->wMinor); // Only reads SoundFont 2.x banks if (fversion->wMajor != 2) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(SF_INVALIDBANK); return NULL; } // Inam is a REQUIRED Info sub-chunk! if (hf->SetBankName(infoCkValues[Inam]) != SUCCESS) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return NULL; } /* * Read SoundFont data into the 'nine heads' */ /* Move to the Articulation Data chunk... */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Pdta))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding PDTA chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } /* Allocate system memory for the Preset Table */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Phdr))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding PHDR chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } presetCnt = (WORD)((tRIFF.GetCkSize() / PRSTHDR_SIZE) - 1); hf->pPHdr = (SFPRESETHDRPTR) Allocate(prstHdr, sizeof(sfPresetHdr), PRSTHDR_SIZE, tRIFF.GetCkSize() , hf); if (hf->pPHdr == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to pbag */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Pbag))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding PBAG chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR ); return (NULL); } hf->pPBag = (SFBAGNDXPTR)Allocate(prstBagNdx, sizeof(sfBagNdx), PRSTBAGNDX_SIZE, tRIFF.GetCkSize(), hf); if (hf->pPBag == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to pmod */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Pmod))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding PMOD chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } hf->pPMod = (SFMODLISTPTR)Allocate(prstModList, sizeof(sfModList), PRSTMODLIST_SIZE, tRIFF.GetCkSize(), hf); if (hf->pPMod == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to pgen */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Pgen))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding PGEN chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } hf->pPGen = (SFGENLISTPTR)Allocate(prstGenList, sizeof(sfGenList), PRSTGENLIST_SIZE, tRIFF.GetCkSize(), hf); if (hf->pPGen == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to inst */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Inst))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding INST chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } hf->pInst = (SFINSTPTR)Allocate(inst, sizeof(sfInst), INST_SIZE, tRIFF.GetCkSize(), hf ); if (hf->pInst == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to ibag */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Ibag))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding IBAG chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } hf->pIBag = (SFBAGNDXPTR)Allocate(instBagNdx, sizeof(sfBagNdx), INSTBAGNDX_SIZE, tRIFF.GetCkSize(), hf); if (hf->pIBag == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to imod */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Imod))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding IMOD chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } hf->pIMod = (SFMODLISTPTR) Allocate(instModList, sizeof(sfModList), INSTMODLIST_SIZE, tRIFF.GetCkSize(), hf); if (hf->pIMod == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to igen */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Igen))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding IGEN chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } hf->pIGen = (SFGENLISTPTR) Allocate(instGenList, sizeof(sfGenList), INSTGENLIST_SIZE, tRIFF.GetCkSize(), hf); if (hf->pIGen == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* Move to shdr */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Shdr))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding SHDR chunk in " << pathName; #endif delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_RIFFERROR); return (NULL); } hf->pSHdr = (SFSAMPLEHDRPTR) Allocate(sampHdr, // kind sizeof(sfSampleHdr), // in mem size SAMPHDRV2_SIZE, // file size tRIFF.GetCkSize(), // chunk size hf ); // update size if (hf->pSHdr == NULL) { delete hf; tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; SetError(EHC_ALLOCATE_PMEM_ERROR); return(NULL); } /* * Store sample size and/or offset for future use */ if (SUCCESS != tRIFF.FindCk(tRIFF.GetRIFFToken(Smpl))) { #ifdef DEBUG qDebug()<<"%ReadSFBFile-E-Error finding SMPL chunk in " << pathName; #endif dwSampleSize = 0; dwSampleOffset = 0; } else { dwSampleSize = tRIFF.GetCkSize(); dwSampleOffset = 0; } /* * The following stuffs data structure members which were not in the * original SoundFont data structures. */ for (WORD x=0;x<hf->awStructSize[inst];x++){ hf->pInst[x].wRefCount = 0; } for (WORD y=0;y<hf->awStructSize[sampHdr];y++){ hf->pSHdr[y].wRefCount = 0; } tRIFF.CloseRIFF(); bySFStorageStatus = SFR_CLOSED; /* * Do Processing of SoundFont data based on system and audio hardware */ /* Swap the order of the bytes in the data structs */ for (uiCount = 0; uiCount < hf->awStructSize[prstHdr]; uiCount++) { tRIFF.SwapBytes(&hf->pPHdr[uiCount].wPresetNum); tRIFF.SwapBytes(&hf->pPHdr[uiCount].wPresetBank); tRIFF.SwapBytes(&hf->pPHdr[uiCount].wBagNdx); /* We now need to swap the DWORDS */ } for (uiCount = 0; uiCount < hf->awStructSize[prstBagNdx]; uiCount++) { tRIFF.SwapBytes(&hf->pPBag[uiCount].wGenNdx); tRIFF.SwapBytes(&hf->pPBag[uiCount].wModNdx); } for (uiCount = 0; uiCount < hf->awStructSize[prstGenList]; uiCount++){ tRIFF.SwapBytes(&hf->pPGen[uiCount].sfGenOper); tRIFF.SwapBytes((WORD*)(&hf->pPGen[uiCount].unAmt)); // The SoundFont 2.0 specification dictates that unknown generators // be ignored. We are doing that by changing its operator value to the // 'nop' operator for the purposes of the enabler. These lines may not // be desirable for an edit engine, which would want to leave data in // tact, and would instead want to be in a seperate verification routine. if (hf->pPGen[uiCount].sfGenOper > endOper) hf->pPGen[uiCount].sfGenOper = nop; } for (uiCount = 0; uiCount < hf->awStructSize[prstModList]; uiCount++) { tRIFF.SwapBytes(&hf->pPMod[uiCount].wModSrcOper); tRIFF.SwapBytes(&hf->pPMod[uiCount].wModDestOper); tRIFF.SwapBytes((WORD*)(&hf->pPMod[uiCount].shAmount)); } /* The instrument layers */ for (uiCount = 0; uiCount < hf->awStructSize[inst]; uiCount++) { tRIFF.SwapBytes(&hf->pInst[uiCount].wBagNdx); } for (uiCount = 0; uiCount < hf->awStructSize[instBagNdx]; uiCount++) { tRIFF.SwapBytes(&hf->pIBag[uiCount].wGenNdx); tRIFF.SwapBytes(&hf->pIBag[uiCount].wModNdx); } for (uiCount = 0; uiCount < hf->awStructSize[instGenList]; uiCount++) { tRIFF.SwapBytes(&hf->pIGen[uiCount].sfGenOper); tRIFF.SwapBytes((WORD*)(&hf->pIGen[uiCount].unAmt)); // The SoundFont 2.0 specification dictates that unknown generators // be ignored. We are doing that by changing its operator value to the // 'nop' operator for the purposes of the enabler. These lines may not // be desirable for an edit engine, which would want to leave data in // tact, and would instead want to be in a seperate verification routine. if (hf->pIGen[uiCount].sfGenOper > endOper) hf->pIGen[uiCount].sfGenOper = nop; } for (uiCount = 0; uiCount < hf->awStructSize[instModList]; uiCount++) { tRIFF.SwapBytes(&hf->pIMod[uiCount].wModSrcOper); tRIFF.SwapBytes(&hf->pIMod[uiCount].wModDestOper); tRIFF.SwapBytes((WORD*)(&hf->pIMod[uiCount].shAmount)); } //// Sample Headers //// for (uiCount = 0; uiCount < hf->awStructSize[sampHdr]; uiCount++) { tRIFF.SwapDWORD(&hf->pSHdr[uiCount].dwStart); tRIFF.SwapDWORD(&hf->pSHdr[uiCount].dwEnd); tRIFF.SwapDWORD(&hf->pSHdr[uiCount].dwStartloop); tRIFF.SwapDWORD(&hf->pSHdr[uiCount].dwEndloop); tRIFF.SwapDWORD(&hf->pSHdr[uiCount].dwSampleRate); //twoByteUnion temp; //temp.byVals.by1 = hf->pSHdr[uiCount].byOriginalKey; //temp.byVals.by0 = hf->pSHdr[uiCount].chFineCorrection; //tRIFF.SwapBytes(&temp.wVal); //hf->pSHdr[uiCount].byOriginalKey = temp.byVals.by1; //hf->pSHdr[uiCount].chFineCorrection = temp.byVals.by0; tRIFF.SwapBytes(&hf->pSHdr[uiCount].wSampleLink); tRIFF.SwapBytes(&hf->pSHdr[uiCount].sfSampleType); if ((hf->pSHdr[uiCount].sfSampleType & romSample) == romSample) bROMSamples = TRUE; hf->pSHdr[uiCount].bSampleLoaded = FALSE; } /* It is here that we can do a valid WaveTable ID Check */ pchIROMChunk = GetInfoSubCkVal(Irom); if ((bROMSamples == TRUE) && (pchIROMChunk == NULL)) { /* ROM samples in a bank with no IROM chunk. Illegal bank. */ SetError(EHC_WRONGWAVETABLE); delete hf; return NULL; } if ((pchReqdWaveTable != NULL) && (pchIROMChunk != NULL)) { /* If the CLIENT did NOT demand that loaded banks using ROM data match a particular WaveTable ID, bypass. If the ROM ID in the SoundFont bank is a null string, there is no required WaveTable for the SF, so bypass. If neither is a null string, AND if the SoundFont bank DOES INDEED contain samples for a particular a WaveTable ROM, do a string comparison between the CLIENT's ID and the SoundFont bank's ID. */ if ((pchReqdWaveTable[0] != '\0') && (pchIROMChunk[0] != '\0') && (bROMSamples == TRUE) && (strcmp(pchReqdWaveTable, pchIROMChunk) != 0)) { /* Non-matching wavetable ID when matching ID demanded, AND the Loaded SoundFont bank does contain samples expected to be in WaveTable ROM. This is an invalid bank for the current synth. */ SetError(EHC_WRONGWAVETABLE); delete hf; return NULL; } } /* Return the hydraClass ptr. */ return hf; } // end ReadSFBFile