Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- typedef struct subchunk_fmt {
- Uint16 format; //1 for pcm, 3 for float (anything else is unsupported)
- Uint16 channels; //number of interleaved channels; L&R for stereo (2)
- Uint32 sampleRate; //number of samples per second, in hertz
- Uint32 byteRate; //the number of bytes per second of audio
- Uint16 blockAlign; //=(channels*bitsPerSample)/8
- Uint16 bitsPerSample;
- //below is only applicable for format -2 (extensible), i think
- Uint16 extensionSize; //=0 or 22
- Uint32 channelMask; //speaker position mask
- union {
- Uint16 format;
- char GUID_s[16];
- Uint64 GUID_n[2];
- } /*----------*/ sub; //guid, including data format code
- } subchunk_fmt;
- #define _CHUNK_HEADER_SIZE (sizeof(Uint32)+sizeof(Uint32))
- typedef struct _subchunk {
- Uint32 id;
- Uint32 size;
- union {
- Uint32 waveID; //part of wave header
- subchunk_fmt fmt;
- Uint32 sampleLength; //# of sample frames; part of "fact" subchunk
- Uint8 data[1]; //only element of "data" subchunk
- };
- } _subchunk;
- typedef struct kit_kmixerPCM {
- kit_kmixerVoiceSpec spec;
- Uint64 dataSize;
- Uint64 numSamples;
- Uint64 loopStart;
- Uint64 loopEnd;
- Uint32 byteRate;
- Uint16 bitsPerSample;
- Uint8 loopCount; //255 (-1) for infinite loop
- Uint8 flags;
- union { //pcm data should be contiguous with the struct itself
- void* data; //should be equal to (void*)pcm_struct+sizeof(kit_kmixerPCM)
- Uint8* u_8;
- Sint16* i16;
- Sint32* i32;
- float* f32;
- struct { Uint8 l; Uint8 r; }* u_8s;
- struct { Sint16 l; Sint16 r; }* i16s;
- struct { Sint32 l; Sint32 r; }* i32s;
- struct { float l; float r; }* f32s;
- };
- } kit_kmixerPCM;
- size_t kit_coreFileSize(const char* filePath){
- size_t fileSize = 0;
- _IF_SDLERR(filePath==NULL,;,"!filePath")
- FILE* file = fopen(filePath,"rb");
- _IF_SDLERR(file==NULL,;,"!fopen")
- int result = fseek(file, 0L, SEEK_END);
- _IF_SDLERR(result,fclose(file),"fseek()=%i",result)
- size_t _fileSize = ftell(file);
- _IF_SDLERR(!_fileSize,fclose(file),"fileSize=0")
- _IF_SDLERR(_fileSize==-1,fclose(file),"fileSize=-1")
- result = fclose(file);
- _IF_SDLERR(result,;,"fclose()=%i",result)
- fileSize = _fileSize;
- _error_:
- return fileSize;
- }
- #define DEFAULT_RW_CHUNK_SIZE 4096
- size_t kit_coreFileReadBin(const char* filePath, void* buffer_p, size_t chunkSize){
- size_t dataSize = 0;
- void* dataStart = NULL;
- size_t fileSize = 0;
- SDL_bool success =SDL_FALSE;
- _IF_SDLERR(buffer_p==NULL,;,"!buffer_p")
- //get size of file, in bytes
- fileSize = kit_coreFileSize(filePath);
- _IF_GOTO_ERROR(!fileSize,;)
- //open file handle
- FILE* file = fopen(filePath,"rb");
- _IF_SDLERR(file==NULL,;,"!fopen")
- //allocate memory for file data
- dataStart = SDL_malloc(fileSize);
- _IF_SDLERR(dataStart==NULL,fclose(file),"!dataStart")
- //read bytes from file into fileData
- if(!chunkSize) chunkSize = DEFAULT_RW_CHUNK_SIZE;
- size_t bytesRead, totalRead = 0;
- void* dataPtr = dataStart;
- void* dataEnd = dataStart+fileSize;
- while((dataPtr+chunkSize) < dataEnd){
- bytesRead = fread(dataPtr,1,chunkSize,file);
- _IF_SDLERR(bytesRead<chunkSize,fclose(file),"!fread; bytesRead<chunkSize")
- totalRead += bytesRead;
- dataPtr += chunkSize;
- }
- size_t remainingBytes = fileSize-totalRead;
- if(remainingBytes) bytesRead = fread(dataPtr,1,remainingBytes,file);
- _IF_SDLERR(bytesRead<remainingBytes,fclose(file),"!fread; bytesRead<remainingBytes")
- //totalRead += bytesRead; (unnecessary)
- //close file handle
- int result = fclose(file);
- _IF_SDLERR(result,;,"fclose()=%i",result)
- success = SDL_TRUE;
- _error_:
- if(success){
- *(void**)buffer_p = dataStart;
- dataSize = fileSize;
- } else if(dataStart!=NULL && !success){
- SDL_free(dataStart);
- }
- return dataSize;
- }
- #define WAVE_FORMAT_PCM 0x0001
- #define WAVE_FORMAT_IEEE_FLOAT 0x0003
- #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
- enum _wav_ids {
- id_RIFF=0x46464952, //="RIFF"
- id_WAVE=0x45564157, //="WAVE"
- id_fmt =0x20746D66, //="fmt "
- id_fact=0x74636166, //="fact"
- //id_PEAK=0x4B414550, //="PEAK"
- id_data=0x61746164, //="data"
- };
- kit_kmixerPCM* kit_kmixerWAVLoad(const char* filePath){
- kit_kmixerPCM* pcm = NULL;
- void* fileDataStart = NULL;
- SDL_bool success = SDL_FALSE;
- size_t fileSize = kit_coreFileReadBin(filePath,&fileDataStart,0);
- _IF_SDLERR(!fileSize,;,"!file")
- _IF_SDLERR(fileSize<44,;,"fileSize<44")
- void* fileDataEnd = fileDataStart+fileSize;
- void* data = fileDataStart; //test file=3996872B
- _IF_GOTO_ERROR(kit_coreRealloc(&pcm,0,sizeof(kit_kmixerPCM)),;)
- SDL_malloc(sizeof(kit_kmixerPCM));
- _IF_SDLERR(pcm==NULL,;,"!pcm")
- //verify wave header
- _subchunk* subchunk = data;
- _IF_SDLERR(subchunk->id!=id_RIFF,;,"chunk ID!=\"RIFF\"")
- _IF_SDLERR(subchunk->size!=(fileSize-8),;,"chunkSize!=(fileSize-8)")
- _IF_SDLERR(subchunk->waveID!=id_WAVE,;,"waveID!=\"WAVE\"")
- data+=_CHUNK_HEADER_SIZE;
- data+=sizeof(Uint32);
- _IF_SDLERR(data>=fileDataEnd,;,"buffer overflow") //should be impossible
- //process subchunks
- SDL_bool has_fmt = SDL_FALSE;
- SDL_bool has_data = SDL_FALSE;
- SDL_bool has_fact = SDL_FALSE; //optional subchunk
- while(data < fileDataEnd){
- subchunk = data;
- switch(subchunk->id){
- case id_fmt:; //contains most pcm info
- //format
- Uint16 bitsPerSample = subchunk->fmt.bitsPerSample;
- Uint16 format=subchunk->fmt.format;
- switch(format){
- case WAVE_FORMAT_PCM: _format_pcm:
- if( bitsPerSample== 8) pcm->spec.format = AUDIO_U8 ;
- else if(bitsPerSample==16) pcm->spec.format = AUDIO_S16;
- else if(bitsPerSample==32) pcm->spec.format = AUDIO_S32;
- else _IS_SDLERR(;,"PCM && bitsPerSample!=<8,16,32>")
- break;
- case WAVE_FORMAT_IEEE_FLOAT: _format_float:
- pcm->spec.format = AUDIO_F32;
- _IF_SDLERR(bitsPerSample!=32,;,"float && bitsPerSample!=32")
- break;
- case WAVE_FORMAT_EXTENSIBLE:
- _IF_SDLERR(subchunk->fmt.extensionSize!=22,;,"extensionSize!=22")
- format=subchunk->fmt.sub.format; //instead of subchunk->fmt.format
- if(format == WAVE_FORMAT_PCM) goto _format_pcm;
- if(format == WAVE_FORMAT_IEEE_FLOAT) goto _format_float;
- SDL_FALLTHROUGH; //go to default when format is not recognized
- default: _IS_SDLERR(;,"unknown format 0x%04X",subchunk->fmt.format) }
- //channels
- _IF_SDLERR(!subchunk->fmt.channels,;,"channels=0")
- _IF_SDLERR(subchunk->fmt.channels>2,;,"channels>2")
- pcm->spec.stereo = subchunk->fmt.channels==2;
- //sampleRate
- _IF_SDLERR(subchunk->fmt.sampleRate<1000,;,"sampleRate<1kHz")
- _IF_SDLERR(subchunk->fmt.sampleRate>384000,;,"sampleRate>384kHz")
- pcm->spec.freq = subchunk->fmt.sampleRate;
- //bitsPerSample
- _IF_SDLERR((bitsPerSample%8)!=0,;,"(bitsPerSample%%8)!=0")
- pcm->bitsPerSample = bitsPerSample;
- //byteRate
- Uint16 bytesPerSample = bitsPerSample/8;
- Uint32 correctByteRate = (bytesPerSample*pcm->spec.freq)<<pcm->spec.stereo;
- _IF_SDLERR(subchunk->fmt.byteRate!=correctByteRate,;,"incorrect byteRate")
- pcm->byteRate = subchunk->fmt.byteRate;
- has_fmt = SDL_TRUE; break;
- case id_data: //contains sample data (contiguous with pcm struct itself)
- //(not using kit_coreRealloc here, because its memset 0 would be redundant)
- pcm = SDL_realloc(pcm, sizeof(kit_kmixerPCM)+subchunk->size);
- _IF_SDLERR(pcm==NULL,;,"!pcm->data")
- pcm->data = (void*)pcm+sizeof(kit_kmixerPCM);
- kit_coreMemcpy(pcm->data, subchunk->data, subchunk->size);
- pcm->dataSize = subchunk->size;
- has_data = SDL_TRUE; break;
- case id_fact: //contains numSamples value
- pcm->numSamples = subchunk->sampleLength;
- has_fact = SDL_TRUE; break;
- default:; //other subchunks are ignored
- }
- data += _CHUNK_HEADER_SIZE;
- data += subchunk->size;
- }
- _IF_SDLERR(!has_fmt,;,"fmt subchunk not found")
- _IF_SDLERR(!has_data,;,"data subchunk not found")
- if(!has_fact){ //if no fact subchunk found, calculate numSamples
- pcm->numSamples = pcm->dataSize;
- pcm->numSamples /= pcm->bitsPerSample/8;
- pcm->numSamples >>= pcm->spec.stereo;
- }
- success = SDL_TRUE;
- _error_:
- if(fileDataStart != NULL) SDL_free(fileDataStart);
- if(pcm!=NULL && !success){
- SDL_free(pcm);
- pcm = NULL;
- }
- return pcm;
- }
- #define FDM_MAGIC_NUMBER 0x006D6466
- typedef struct kit_kmixerFDMHeader {
- union {
- char s[4]; //="fdm\x00"
- Uint32 n; //=0x006D6466
- } /*------*/ magic;
- Uint16 headerSize; //headerSize includes headerSize itself, and magic
- Uint16 type; //type 0 = static delta, static history
- Uint64 dataSize;
- Uint64 numSamples;
- Uint64 loopStart;
- Uint64 loopEnd;
- float delta; //% of change, relative to HALF range; 0.0 -> 2.0
- Uint8 loopCount; //255 (-1) for inf. loop
- Uint8 remainder; //=numSamples%8
- Uint8 historyLen; //number of samples in filter; 0 -> 63
- Uint8 channels;
- } kit_kmixerFDMHeader;
- /* WIP
- static inline Sint32 _getDelta(Sint16 input, Sint32 current, Sint32 deltaMax,
- Uint64 history, Uint8 historyLen)
- {
- if
- history = (history<<1)
- int _historyLen = historyLen;
- int historyBitCount=0;
- while(_historyLen--){
- historyBitCount += history&1;
- history>>=1;
- }
- float fraction = -1 + ;
- Sint32 new = input;
- }
- Uint16 _kit_kmixerFDMEncode(Uint8* output, Sint16* input, kit_kmixerFDMHeader* hdr){
- Uint64 numSamples = hdr->numSamples;
- Uint64 totalError = 0;
- Uint8 historyLen = hdr->historyLen;
- Sint32 deltaMax = hdr->delta*32767;
- if(hdr->channels==1){
- Uint64 history;
- Uint8 currentByte;
- Sint32 currentValue, currentDelta;
- for(Uint64 i=0; i<numSamples; ++i){
- }
- } else { //assumed stereo
- //struct { Sint16 l; Sint16 r; }* input_s = (void*)input;
- //for(Uint64 i=0; i<numSamples; ++i)
- }
- return totalError / numSamples;
- }
- */
- int kit_kmixerFDMWrite(const char* fileName, kit_kmixerPCM* pcm,
- Uint8 historyLen, Uint8 iterations)
- {
- int returnStatus = 0;
- Sint16* input = NULL;
- Uint8* outputs[2] = {NULL,NULL};
- float quantErrors[2] = {2,2};
- _IF_SDLERR(fileName==NULL,;,"!fileName")
- _IF_SDLERR(pcm==NULL,;,"!pcm");
- _IF_SDLERR(historyLen>63,;,"historyLen>63")
- _IF_SDLERR(iterations==0,;,"iterations=0")
- //fill in header info
- _IF_SDLERR(pcm->numSamples==0,;,"numSamples==0")
- kit_kmixerFDMHeader header;
- header.magic.n = FDM_MAGIC_NUMBER; //"fdm\x00"
- header.headerSize = sizeof(kit_kmixerFDMHeader);
- header.type = 0; //type 0 = static delta, static history
- float dataSizeMono = ceilf((float)pcm->numSamples/8);
- header.dataSize = dataSizeMono*(1+pcm->spec.stereo);
- header.numSamples = pcm->numSamples;
- header.loopStart = pcm->loopStart;
- header.loopEnd = pcm->loopEnd;
- header.delta = 2.0f; //(final value calculated)
- header.loopCount = pcm->loopCount;
- header.remainder = pcm->numSamples%8;
- header.historyLen = historyLen;
- header.channels = 1+pcm->spec.stereo;
- //malloc i/o buffers
- Uint64 numSamplesRaw = header.numSamples*header.channels;
- input = SDL_malloc(sizeof(Sint16)*numSamplesRaw);
- outputs[0] = SDL_malloc(header.dataSize);
- outputs[1] = SDL_malloc(header.dataSize);
- _IF_SDLERR(input==NULL,;,"!input")
- _IF_SDLERR(outputs[0]==NULL,;,"!outputs[0]")
- _IF_SDLERR(outputs[1]==NULL,;,"!outputs[1]")
- //convert sample data to Sint16
- Sint8* pcmI_8 = pcm->data; Sint32* pcmI32 = pcm->i32; float* pcmF32 = pcm->f32;
- switch(pcm->spec.format){
- case AUDIO_U8 : for(Uint64 i=0; i<numSamplesRaw; ++i){ input[i] =(pcmI_8[i]-128)<<8; } break;
- case AUDIO_S16: kit_coreMemcpy(input,pcm->i16,sizeof(Sint16)*numSamplesRaw); break;
- case AUDIO_S32: for(Uint64 i=0; i<numSamplesRaw; ++i){ input[i] = pcmI32[i]>>16; } break;
- case AUDIO_F32: for(Uint64 i=0; i<numSamplesRaw; ++i){ input[i] = pcmF32[i]*32767; } }
- for(Uint64 i=0; i<numSamplesRaw; ++i){ if(input[i]==-32768) input[i] = -32767; }
- //encode i16 pcm stream
- //int which = 0; //which output buffer to write to
- //write output data to file
- //write header info first
- FILE* file = fopen(fileName,"wb");
- _IF_SDLERR(file==NULL,;,"!file")
- size_t headerBytes = fwrite(&header,1,sizeof(kit_kmixerFDMHeader),file);
- _IF_SDLERR(headerBytes<sizeof(header),fclose(file),"headerBytes<sizeof(header)")
- //then write data
- const size_t chunkSize = DEFAULT_RW_CHUNK_SIZE;
- size_t bytesWritten, totalWritten = 0; //specifically data bytes
- void* dataStart = (quantErrors[0]<quantErrors[1]) ? outputs[0] : outputs[1];
- void* dataPtr = dataStart;
- void* dataEnd = dataStart + header.dataSize;
- while((dataPtr+chunkSize) < dataEnd){
- bytesWritten = fwrite(dataPtr,1,chunkSize,file);
- _IF_SDLERR(bytesWritten<chunkSize,fclose(file),"!fwrite; bytesWritten<chunkSize")
- totalWritten += bytesWritten;
- dataPtr += chunkSize;
- }
- size_t remainingBytes = header.dataSize-totalWritten;
- if(remainingBytes) bytesWritten = fwrite(dataPtr,1,remainingBytes,file);
- _IF_SDLERR(bytesWritten<remainingBytes,fclose(file),"!fwrite; bytesWritten<remainingBytes")
- int result = fclose(file);
- _IF_SDLERR(result,;,"fclose()=%i",result)
- ++returnStatus;
- _error_:
- --returnStatus;
- if(input != NULL) SDL_free(input);
- if(outputs[0] != NULL) SDL_free(outputs[0]);
- if(outputs[1] != NULL) SDL_free(outputs[1]);
- return returnStatus;
- }
Advertisement
Comments
-
- Title: "OptimaEquipments.com: Your Destination for High-Quality MRI and CT Scanners - Advancing Medical Imaging Technology"
- Introduction
- In the ever-evolving world of healthcare, medical imaging technology plays a pivotal role in diagnosing and treating various medical conditions. Among the most crucial equipment used in modern medical facilities are MRI (Magnetic Resonance Imaging) and CT (Computed Tomography) scanners. These state-of-the-art machines have revolutionized medical diagnostics and significantly improved patient care. If you're in the medical field and seeking high-quality medical imaging equipment,
- https://optimaequipments.com/
- [url=https://optimaequipments.com/product/mindray-m7-ultrasound-machine/]Mindray M7 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/sonimage-hs1/]SONIMAGE® HS1[/url]
- [url=https://optimaequipments.com/product/sonimage-mx1/]SONIMAGE® MX1[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-nx2-ultrasound-machine/]Siemens Acuson NX2 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-nx3-elite-ultrasound-machine/]Siemens Acuson NX3 Elite Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-nx3-ultrasound-machine/]Siemens Acuson NX3 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-p300-ultrasound-machine/]Siemens Acuson P300 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-p500-ultrasound-machine/]Siemens Acuson P500 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-s1000-ultrasound-machine/]Siemens Acuson S1000 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-sc2000-ultrasound-machine/]Siemens Acuson SC2000 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/siemens-acuson-x150-ultrasound-machine/]Siemens Acuson X150 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/samsung-sonoace-r7-ultrasound-machine/]Samsung SonoAce R7 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/samsung-accuvix-v10-ultrasound-machine/]Samsung Accuvix V10 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/samsung-accuvix-xg-ultrasound-machine/]Samsung Accuvix XG Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/samsung-mysono-u6-ultrasound-machine/]Samsung MySono U6 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/samsung-sonoace-r3-ultrasound-machine/]Samsung SonoAce R3 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/samsung-sonoace-r5-ultrasound-machine/]Samsung SonoAce R5 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/canon-aplio-300-cv-platinum-ultrasound-machine/]Canon Aplio 300 CV Platinum Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/canon-aplio-400-platinum-ultrasound-machine/]Canon Aplio 400 Platinum Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/canon-aplio-i700-ultrasound-machine/]Canon Aplio i700 Ultrasound Machine[/url]
- [url=https://optimaequipments.com/product/canon-artida-ultrasound-machine/]Canon Artida Ultrasound Machine[/url]
Add Comment
Please, Sign In to add comment
Advertisement