static __inline__ int read_adpcm_block_headers(Sound_Sample *sample) { Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; SDL_RWops *rw = internal->rw; wav_t *w = (wav_t *) internal->decoder_private; fmt_t *fmt = w->fmt; ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders; int i; int max = fmt->wChannels; if (w->bytesLeft < fmt->wBlockAlign) { sample->flags |= SOUND_SAMPLEFLAG_EOF; return(0); } /* if */ w->bytesLeft -= fmt->wBlockAlign; for (i = 0; i < max; i++) BAIL_IF_MACRO(!read_uint8(rw, &headers[i].bPredictor), NULL, 0); for (i = 0; i < max; i++) BAIL_IF_MACRO(!read_le16(rw, &headers[i].iDelta), NULL, 0); for (i = 0; i < max; i++) BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp1), NULL, 0); for (i = 0; i < max; i++) BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp2), NULL, 0); fmt->fmt.adpcm.samples_left_in_block = fmt->fmt.adpcm.wSamplesPerBlock; fmt->fmt.adpcm.nibble_state = 0; return(1); } /* read_adpcm_block_headers */
int pcx_load_image(const char *path, struct image *image) { FILE *file; uint8_t *data = NULL; if (!(file = fopen(path, "rb"))) { error_errno("Opening file '%s' failed", path); goto failure; } uint8_t header[PCX_HEADER_SIZE]; if (fread(header, PCX_HEADER_SIZE, 1, file) != 1) { error_errno("Reading PCX header from file '%s' failed", path); goto failure; } int width = read_le16(header + PCX_X2) - read_le16(header + PCX_X1) + 1; int height = read_le16(header + PCX_Y2) - read_le16(header + PCX_Y1) + 1; int size = width * height; data = xmalloc(size); uint8_t *p = data; int pixel, count; for (int i = 0; i < size; ) { if ((pixel = fgetc(file)) == EOF) { error_errno("Reading image data from file '%s' failed", path); goto failure; } if (pixel < 192) { *p++ = (uint8_t) pixel; i++; } else { count = pixel - 192; if ((pixel = fgetc(file)) == EOF) { error_errno("Reading image data from file '%s' failed", path); goto failure; } while (count-- > 0) { *p++ = (uint8_t) pixel; i++; } } } fclose(file); init_image(image, width, height, data); return 0; failure: if (file) fclose(file); if (data) xfree(data); return -1; }
static void Modulator_read(Modulator *self, Reader *stream) { self->mSrcOp = read_le16(stream); self->mDstOp = read_le16(stream); self->mAmount = read_le16(stream); self->mAmtSrcOp = read_le16(stream); self->mTransOp = read_le16(stream); }
static void PresetHeader_read(PresetHeader *self, Reader *stream) { Reader_read(stream, self->mName, sizeof(self->mName)); self->mPreset = read_le16(stream); self->mBank = read_le16(stream); self->mZoneIdx = read_le16(stream); self->mLibrary = read_le32(stream); self->mGenre = read_le32(stream); self->mMorphology = read_le32(stream); }
/* Return 0 if equal. Non-zero if not equal. */ static int guid_compare(const EFI_GUID *le_guid, const EFI_GUID *native_guid) { if (read_le32(&le_guid->Data1) != native_guid->Data1) return 1; if (read_le16(&le_guid->Data2) != native_guid->Data2) return 1; if (read_le16(&le_guid->Data3) != native_guid->Data3) return 1; return memcmp(le_guid->Data4, native_guid->Data4, ARRAY_SIZE(le_guid->Data4)); }
static void SampleHeader_read(SampleHeader *self, Reader *stream) { Reader_read(stream, self->mName, sizeof(self->mName)); self->mStart = read_le32(stream); self->mEnd = read_le32(stream); self->mStartloop = read_le32(stream); self->mEndloop = read_le32(stream); self->mSampleRate = read_le32(stream); self->mOriginalKey = read_8(stream); self->mCorrection = read_8(stream); self->mSampleLink = read_le16(stream); self->mSampleType = read_le16(stream); }
/* cr50 uses bytes 3:2 of status register for burst count and * all 4 bytes must be read */ static int cr50_i2c_wait_burststs(struct tpm_chip *chip, uint8_t mask, size_t *burst, int *status) { uint8_t buf[4]; struct stopwatch sw; stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_LONG_MS); while (!stopwatch_expired(&sw)) { if (cr50_i2c_read(chip, TPM_STS(chip->vendor.locality), buf, sizeof(buf)) != 0) { mdelay(CR50_TIMEOUT_SHORT_MS); continue; } *status = buf[0]; *burst = read_le16(&buf[1]); /* Check if mask matches and burst is valid */ if ((*status & mask) == mask && *burst > 0 && *burst <= CR50_MAX_BUFSIZE) return 0; mdelay(CR50_TIMEOUT_SHORT_MS); } printk(BIOS_ERR, "%s: Timeout reading burst and status\n", __func__); return -1; }
/* * Read in a fmt_t from disk. This makes this process safe regardless of * the processor's byte order or how the fmt_t structure is packed. * Note that the union "fmt" is not read in here; that is handled as * needed in the read_fmt_* functions. */ static int read_fmt_chunk(SDL_RWops *rw, fmt_t *fmt) { /* skip reading the chunk ID, since it was already read at this point... */ fmt->chunkID = fmtID; BAIL_IF_MACRO(!read_le32(rw, &fmt->chunkSize), NULL, 0); BAIL_IF_MACRO(fmt->chunkSize < 16, "WAV: Invalid chunk size", 0); fmt->next_chunk_offset = SDL_RWtell(rw) + fmt->chunkSize; BAIL_IF_MACRO(!read_le16(rw, &fmt->wFormatTag), NULL, 0); BAIL_IF_MACRO(!read_le16(rw, &fmt->wChannels), NULL, 0); BAIL_IF_MACRO(!read_le32(rw, &fmt->dwSamplesPerSec), NULL, 0); BAIL_IF_MACRO(!read_le32(rw, &fmt->dwAvgBytesPerSec), NULL, 0); BAIL_IF_MACRO(!read_le16(rw, &fmt->wBlockAlign), NULL, 0); BAIL_IF_MACRO(!read_le16(rw, &fmt->wBitsPerSample), NULL, 0); return(1); } /* read_fmt_chunk */
void BsaArchive::load(const std::string &fname) { mFilename = fname; std::ifstream stream(mFilename.c_str(), std::ios::binary); if(!stream.is_open()) throw std::runtime_error("Failed to open "+mFilename); size_t count = read_le16(stream); mEntries.reserve(count); loadNamed(count, stream); }
void BsaArchive::loadNamed(size_t count, std::istream& stream) { std::vector<std::string> names; names.reserve(count); std::vector<Entry> entries; entries.reserve(count); std::streamsize base = stream.tellg(); if(!stream.seekg(std::streampos(count) * -18, std::ios_base::end)) throw std::runtime_error("Failed to seek to archive footer ("+std::to_string(count)+" entries)"); for(size_t i = 0;i < count;++i) { std::array<char,13> name; stream.read(name.data(), name.size()-1); name.back() = '\0'; // Ensure null termination std::replace(name.begin(), name.end(), '\\', '/'); names.push_back(std::string(name.data())); int iscompressed = read_le16(stream); if(iscompressed != 0) throw std::runtime_error("Compressed entries not supported"); Entry entry; entry.mStart = ((i == 0) ? base : entries[i-1].mEnd); entry.mEnd = entry.mStart + read_le32(stream); entries.push_back(entry); } if(!stream.good()) throw std::runtime_error("Failed reading archive footer"); for(const std::string &name : names) { auto iter = std::lower_bound(mLookupName.begin(), mLookupName.end(), name); if(iter == mLookupName.end() || *iter != name) mLookupName.insert(iter, name); } mEntries.resize(mLookupName.size()); for(size_t i = 0;i < count;++i) { auto iter = std::find(mLookupName.cbegin(), mLookupName.cend(), names[i]); mEntries[std::distance(mLookupName.cbegin(), iter)] = entries[i]; } }
static int relocate_patch_table(void *fsp, size_t size, size_t offset, ssize_t adjustment) { struct fsp_patch_table *table; size_t num; size_t num_entries; table = relative_offset(fsp, offset); if ((offset + sizeof(*table) > size) || (read_le16(&table->header_length) + offset) > size) { printk(BIOS_ERR, "FSPP not entirely contained in region.\n"); return -1; } num_entries = read_le32(&table->patch_entry_num); printk(FSP_DBG_LVL, "FSPP relocs: %zx\n", num_entries); for (num = 0; num < num_entries; num++) { uint32_t *reloc; uint32_t reloc_val; reloc = fspp_reloc(fsp, size, read_le32(&table->patch_entries[num])); if (reloc == NULL) { printk(BIOS_ERR, "Ignoring FSPP entry: %x\n", read_le32(&table->patch_entries[num])); continue; } reloc_val = read_le32(reloc); printk(FSP_DBG_LVL, "Adjusting %p %x -> %x\n", reloc, reloc_val, (unsigned int)(reloc_val + adjustment)); write_le32(reloc, reloc_val + adjustment); } return 0; }
/* Open a VMFS volume */ vmfs_volume_t *vmfs_vol_open(const char *filename,vmfs_flags_t flags) { vmfs_volume_t *vol; struct stat st; int file_flags; if (!(vol = calloc(1,sizeof(*vol)))) return NULL; if (!(vol->device = strdup(filename))) goto err_filename; file_flags = (flags.read_write) ? O_RDWR : O_RDONLY; if ((vol->fd = open(vol->device,file_flags)) < 0) { perror("open"); goto err_open; } vol->flags = flags; fstat(vol->fd,&st); vol->is_blkdev = S_ISBLK(st.st_mode); #if defined(O_DIRECT) || defined(DIRECTIO_ON) if (vol->is_blkdev) #ifdef O_DIRECT fcntl(vol->fd, F_SETFL, O_DIRECT); #else #ifdef DIRECTIO_ON directio(vol->fd, DIRECTIO_ON); #endif #endif #endif vol->vmfs_base = VMFS_VOLINFO_BASE; /* Read volume information */ do { DECL_ALIGNED_BUFFER(buf,512); uint16_t magic; /* Look for the MBR magic number */ m_pread(vol->fd,buf,buf_len,0); magic = read_le16(buf, 510); if (magic == 0xaa55) { /* Scan partition table */ int off; for (off = 446; off < 510; off += 16) { if (buf[off + 4] == 0xfb) { vol->vmfs_base += (off_t) read_le32(buf, off + 8) * 512; break; } } } } while(0); if (vmfs_volinfo_read(vol) == -1) goto err_open; /* We support only VMFS3 and VMFS5*/ if ((vol->vol_info.version != 3) && (vol->vol_info.version != 5)) { fprintf(stderr,"VMFS: Unsupported version %u\n",vol->vol_info.version); goto err_open; } if ((vol->vol_info.version == 5) && flags.read_write) { fprintf(stderr, "VMFS: Can't open VMFS read/write\n"); goto err_open; } if (vol->is_blkdev && (scsi_get_lun(vol->fd) != vol->vol_info.lun)) fprintf(stderr,"VMFS: Warning: Lun ID mismatch on %s\n", vol->device); vmfs_vol_check_reservation(vol); if (vol->flags.debug_level > 0) { printf("VMFS: volume opened successfully\n"); } vol->dev.read = vmfs_vol_read; if (vol->flags.read_write) vol->dev.write = vmfs_vol_write; vol->dev.close = vmfs_vol_close; vol->dev.uuid = &vol->vol_info.lvm_uuid; return vol; err_open: free(vol->device); err_filename: free(vol); return NULL; }
static ssize_t relocate_fvh(uintptr_t new_addr, void *fsp, size_t fsp_size, size_t fvh_offset, size_t *fih_offset) { EFI_FIRMWARE_VOLUME_HEADER *fvh; EFI_FFS_FILE_HEADER *ffsfh; EFI_COMMON_SECTION_HEADER *csh; size_t offset; size_t file_offset; size_t size; size_t fv_length; offset = fvh_offset; fvh = relative_offset(fsp, offset); if (read_le32(&fvh->Signature) != EFI_FVH_SIGNATURE) return -1; fv_length = read_le64(&fvh->FvLength); printk(FSP_DBG_LVL, "FVH length: %zx Offset: %zx Mapping length: %zx\n", fv_length, offset, fsp_size); if (fv_length + offset > fsp_size) return -1; /* Parse only this FV. However, the algorithm uses offsets into the * entire FSP region so make size include the starting offset. */ size = fv_length + offset; if (guid_compare(&fvh->FileSystemGuid, &ffs2_guid)) { printk(BIOS_ERR, "FVH not an FFS2 type.\n"); return -1; } if (read_le16(&fvh->ExtHeaderOffset) != 0) { EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh; offset += read_le16(&fvh->ExtHeaderOffset); fveh = relative_offset(fsp, offset); printk(FSP_DBG_LVL, "Extended Header Offset: %zx Size: %zx\n", (size_t)read_le16(&fvh->ExtHeaderOffset), (size_t)read_le32(&fveh->ExtHeaderSize)); offset += read_le32(&fveh->ExtHeaderSize); /* FFS files are 8 byte aligned after extended header. */ offset = ALIGN_UP(offset, 8); } else { offset += read_le16(&fvh->HeaderLength); } file_offset = offset; while (file_offset + sizeof(*ffsfh) < size) { offset = file_offset; printk(FSP_DBG_LVL, "file offset: %zx\n", file_offset); /* First file and section should be FSP info header. */ if (fih_offset != NULL && *fih_offset == 0) *fih_offset = file_offset; ffsfh = relative_offset(fsp, file_offset); printk(FSP_DBG_LVL, "file type = %x\n", read_le8(&ffsfh->Type)); printk(FSP_DBG_LVL, "file attribs = %x\n", read_le8(&ffsfh->Attributes)); /* Exit FV relocation when empty space found */ if (read_le8(&ffsfh->Type) == EFI_FV_FILETYPE_FFS_MAX) break; /* Next file on 8 byte alignment. */ file_offset += ffs_file_size(ffsfh); file_offset = ALIGN_UP(file_offset, 8); /* Padding files have no section information. */ if (read_le8(&ffsfh->Type) == EFI_FV_FILETYPE_FFS_PAD) continue; offset += file_section_offset(ffsfh); while (offset + sizeof(*csh) < file_offset) { size_t data_size; size_t data_offset; csh = relative_offset(fsp, offset); printk(FSP_DBG_LVL, "section offset: %zx\n", offset); printk(FSP_DBG_LVL, "section type: %x\n", read_le8(&csh->Type)); data_size = section_data_size(csh); data_offset = section_data_offset(csh); if (data_size + data_offset + offset > file_offset) { printk(BIOS_ERR, "Section exceeds FV size.\n"); return -1; } /* * The entire FSP 1.1 image can be thought of as one * program with a single link address even though there * are multiple TEs linked separately. The reason is * that each TE is linked for XIP. So in order to * relocate the TE properly we need to form the * relocated address based on the TE offset within * FSP proper. */ if (read_le8(&csh->Type) == EFI_SECTION_TE) { void *te; size_t te_offset = offset + data_offset; uintptr_t te_addr = new_addr + te_offset; printk(FSP_DBG_LVL, "TE image at offset %zx\n", te_offset); te = relative_offset(fsp, te_offset); te_relocate(te_addr, te); } offset += data_size + data_offset; /* Sections are aligned to 4 bytes. */ offset = ALIGN_UP(offset, 4); } } /* Return amount of buffer parsed: FV size. */ return fv_length; }
BmpHeader* hdr = (BmpHeader*)file; const u32 ofs = read_le32(&hdr->bfOffBits); ENSURE(ofs >= hdr_size && "bmp_hdr_size invalid"); return ofs; } return hdr_size; } // requirements: uncompressed, direct colour, bottom up static Status bmp_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t) { const BmpHeader* hdr = (const BmpHeader*)data; const long w = (long)read_le32(&hdr->biWidth); const long h_ = (long)read_le32(&hdr->biHeight); const u16 bpp = read_le16(&hdr->biBitCount); const u32 compress = read_le32(&hdr->biCompression); const long h = abs(h_); size_t flags = 0; flags |= (h_ < 0)? TEX_TOP_DOWN : TEX_BOTTOM_UP; if(bpp > 16) flags |= TEX_BGR; if(bpp == 32) flags |= TEX_ALPHA; // sanity checks if(compress != BI_RGB) WARN_RETURN(ERR::TEX_COMPRESSED);
static int te_relocate(uintptr_t new_addr, void *te) { EFI_TE_IMAGE_HEADER *teih; EFI_IMAGE_DATA_DIRECTORY *relocd; EFI_IMAGE_BASE_RELOCATION *relocb; uintptr_t image_base; size_t fixup_offset; size_t num_relocs; uint16_t *reloc; size_t relocd_offset; uint8_t *te_base; uint32_t adj; teih = te; if (read_le16(&teih->Signature) != EFI_TE_IMAGE_HEADER_SIGNATURE) { printk(BIOS_ERR, "TE Signature mismatch: %x vs %x\n", read_le16(&teih->Signature), EFI_TE_IMAGE_HEADER_SIGNATURE); return -1; } /* * A TE image is created by converting a PE file. Because of this * the offsets within the headers are off. In order to calculate * the correct releative offets one needs to subtract fixup_offset * from the encoded offets. Similarly, the linked address of the * program is found by adding the fixup_offset to the ImageBase. */ fixup_offset = read_le16(&teih->StrippedSize); fixup_offset -= sizeof(EFI_TE_IMAGE_HEADER); /* Keep track of a base that is correctly adjusted so that offsets * can be used directly. */ te_base = te; te_base -= fixup_offset; image_base = read_le64(&teih->ImageBase); adj = new_addr - (image_base + fixup_offset); printk(FSP_DBG_LVL, "TE Image %p -> %p adjust value: %x\n", (void *)image_base, (void *)new_addr, adj); /* Adjust ImageBase for consistency. */ write_le64(&teih->ImageBase, (uint32_t)(image_base + adj)); relocd = &teih->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC]; relocd_offset = 0; /* Though the field name is VirtualAddress it's actually relative to * the beginning of the image which is linked at ImageBase. */ relocb = relative_offset(te, read_le32(&relocd->VirtualAddress) - fixup_offset); while (relocd_offset < read_le32(&relocd->Size)) { size_t rva_offset = read_le32(&relocb->VirtualAddress); printk(FSP_DBG_LVL, "Relocs for RVA offset %zx\n", rva_offset); num_relocs = read_le32(&relocb->SizeOfBlock) - sizeof(*relocb); num_relocs /= sizeof(uint16_t); reloc = relative_offset(relocb, sizeof(*relocb)); printk(FSP_DBG_LVL, "Num relocs in block: %zx\n", num_relocs); while (num_relocs > 0) { uint16_t reloc_val = read_le16(reloc); int type = reloc_type(reloc_val); size_t offset = reloc_offset(reloc_val); printk(FSP_DBG_LVL, "reloc type %x offset %zx\n", type, offset); if (type == EFI_IMAGE_REL_BASED_HIGHLOW) { uint32_t *reloc_addr; uint32_t val; offset += rva_offset; reloc_addr = (void *)&te_base[offset]; val = read_le32(reloc_addr); printk(FSP_DBG_LVL, "Adjusting %p %x -> %x\n", reloc_addr, val, val + adj); write_le32(reloc_addr, val + adj); } else if (type != EFI_IMAGE_REL_BASED_ABSOLUTE) { printk(BIOS_ERR, "Unknown reloc type: %x\n", type); return -1; } num_relocs--; reloc++; } /* Track consumption of relocation directory contents. */ relocd_offset += read_le32(&relocb->SizeOfBlock); /* Get next relocation block to process. */ relocb = relative_offset(relocb, read_le32(&relocb->SizeOfBlock)); } return 0; }
short getShort() { return read_le16(); }
unsigned short getUShort() { return read_le16(); }
wavStream(std::istream *_fstream) : alureStream(_fstream), format(0), dataStart(0) { ALubyte buffer[25]; ALuint length; if(!fstream->read(reinterpret_cast<char*>(buffer), 12) || memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0) return; while(!dataStart || format == AL_NONE) { char tag[4]; if(!fstream->read(tag, 4)) break; /* read chunk length */ length = read_le32(fstream); if(memcmp(tag, "fmt ", 4) == 0 && length >= 16) { /* Data type (should be 1 for PCM data, 3 for float PCM data, * 7 for muLaw, and 17 for IMA4 data) */ int type = read_le16(fstream); if(type != 0x0001 && type != 0x0003 && type != 0x0007 && type != 0x0011) break; /* mono or stereo data */ channels = read_le16(fstream); /* sample frequency */ samplerate = read_le32(fstream); /* skip average bytes per second */ fstream->ignore(4); /* bytes per block */ blockAlign = read_le16(fstream); if(blockAlign == 0) break; /* bits per sample */ sampleSize = read_le16(fstream); length -= 16; /* Look for any extra data and try to find the format */ ALuint extrabytes = 0; if(length >= 2) { extrabytes = read_le16(fstream); length -= 2; } extrabytes = std::min<ALuint>(extrabytes, length); if(type == 0x0001) format = GetSampleFormat(channels, sampleSize, false); else if(type == 0x0003) format = GetSampleFormat(channels, sampleSize, true); else if(type == 0x0007) { if(sampleSize == 8) { if(channels == 1) format = AL_FORMAT_MONO_MULAW; else if(channels == 2) format = AL_FORMAT_STEREO_MULAW; else if(channels == 4) format = AL_FORMAT_QUAD_MULAW; else if(channels == 6) format = AL_FORMAT_51CHN_MULAW; else if(channels == 7) format = AL_FORMAT_61CHN_MULAW; else if(channels == 8) format = AL_FORMAT_71CHN_MULAW; } } else if(type == 0x0011 && extrabytes >= 2) { int samples = read_le16(fstream); length -= 2; /* AL_EXT_IMA4 only supports 36 bytes-per-channel block * alignment, which has 65 uncompressed sample frames */ if(blockAlign == 36*channels && samples == 65*channels && alIsExtensionPresent("AL_EXT_IMA4")) { if(channels == 1) format = AL_FORMAT_MONO_IMA4; else if(channels == 2) format = AL_FORMAT_STEREO_IMA4; } } } else if(memcmp(tag, "data", 4) == 0) { dataStart = fstream->tellg(); dataLen = remLen = length; } fstream->seekg(length, std::ios_base::cur); } if(dataStart > 0 && format != AL_NONE) fstream->seekg(dataStart); }
ALuint WaveDecoder::read(ALvoid *ptr, ALuint count) { mFile->clear(); auto pos = mFile->tellg(); size_t len = count * mFrameSize; ALuint total = 0; if(pos < mEnd) { len = std::min<std::istream::pos_type>(len, mEnd-pos); #ifdef __BIG_ENDIAN__ switch(mSampleType) { case SampleType_Float32: while(total < len && mFile->good() && !mFile->eof()) { char temp[256]; size_t todo = std::min(len-total, sizeof(temp)); mFile->read(temp, todo); std::streamsize got = mFile->gcount(); for(std::streamsize i = 0;i < got;++i) reinterpret_cast<char*>(ptr)[total+i] = temp[i^3]; total += got; } total /= mFrameSize; break; case SampleType_Int16: while(total < len && mFile->good() && !mFile->eof()) { char temp[256]; size_t todo = std::min(len-total, sizeof(temp)); mFile->read(temp, todo); std::streamsize got = mFile->gcount(); for(std::streamsize i = 0;i < got;++i) reinterpret_cast<char*>(ptr)[total+i] = temp[i^1]; total += got; } total /= mFrameSize; break; case SampleType_UInt8: case SampleType_Mulaw: #else { #endif mFile->read(reinterpret_cast<char*>(ptr), len); total = mFile->gcount() / mFrameSize; } } return total; } SharedPtr<Decoder> WaveDecoderFactory::createDecoder(SharedPtr<std::istream> file) { ChannelConfig channels = ChannelConfig_Mono; SampleType type = SampleType_UInt8; ALuint frequency = 0; ALuint framesize = 0; ALuint loop_pts[2]{0, 0}; ALuint blockalign = 0; ALuint framealign = 0; char tag[4]{}; if(!file->read(tag, 4) || file->gcount() != 4 || memcmp(tag, "RIFF", 4) != 0) return SharedPtr<Decoder>(nullptr); ALuint totalsize = read_le32(*file) & ~1u; if(!file->read(tag, 4) || file->gcount() != 4 || memcmp(tag, "WAVE", 4) != 0) return SharedPtr<Decoder>(nullptr); while(file->good() && !file->eof() && totalsize > 8) { if(!file->read(tag, 4) || file->gcount() != 4) return SharedPtr<Decoder>(nullptr); ALuint size = read_le32(*file); if(size < 2) return SharedPtr<Decoder>(nullptr); totalsize -= 8; size = std::min((size+1) & ~1u, totalsize); totalsize -= size; if(memcmp(tag, "fmt ", 4) == 0) { /* 'fmt ' tag needs at least 16 bytes. */ if(size < 16) goto next_chunk; /* format type */ ALushort fmttype = read_le16(*file); size -= 2; /* mono or stereo data */ int chancount = read_le16(*file); size -= 2; /* sample frequency */ frequency = read_le32(*file); size -= 4; /* skip average bytes per second */ read_le32(*file); size -= 4; /* bytes per block */ blockalign = read_le16(*file); size -= 2; /* bits per sample */ int bitdepth = read_le16(*file); size -= 2; /* Look for any extra data and try to find the format */ ALuint extrabytes = 0; if(size >= 2) { extrabytes = read_le16(*file); size -= 2; } extrabytes = std::min<ALuint>(extrabytes, size); /* Format type should be 0x0001 for integer PCM data, 0x0003 for * float PCM data, 0x0007 for muLaw, and 0xFFFE extensible data. */ if(fmttype == 0x0001) { if(chancount == 1) channels = ChannelConfig_Mono; else if(chancount == 2) channels = ChannelConfig_Stereo; else goto next_chunk; if(bitdepth == 8) type = SampleType_UInt8; else if(bitdepth == 16) type = SampleType_Int16; else goto next_chunk; } else if(fmttype == 0x0003) { if(chancount == 1) channels = ChannelConfig_Mono; else if(chancount == 2) channels = ChannelConfig_Stereo; else goto next_chunk; if(bitdepth == 32) type = SampleType_Float32; else goto next_chunk; } else if(fmttype == 0x0007) { if(chancount == 1) channels = ChannelConfig_Mono; else if(chancount == 2) channels = ChannelConfig_Stereo; else goto next_chunk; if(bitdepth == 8) type = SampleType_Mulaw; else goto next_chunk; } else if(fmttype == 0xFFFE) { if(size < 22) goto next_chunk; char subtype[16]; ALushort validbits = read_le16(*file); size -= 2; ALuint chanmask = read_le32(*file); size -= 4; file->read(subtype, 16); size -= file->gcount(); /* Padded bit depths not supported */ if(validbits != bitdepth) goto next_chunk; if(memcmp(subtype, SUBTYPE_BFORMAT_PCM, 16) == 0 || memcmp(subtype, SUBTYPE_BFORMAT_FLOAT, 16) == 0) { if(chanmask != 0) goto next_chunk; if(chancount == 3) channels = ChannelConfig_BFmt_WXY; else if(chancount == 4) channels = ChannelConfig_BFmt_WXYZ; else goto next_chunk; } else if(memcmp(subtype, SUBTYPE_PCM, 16) == 0 || memcmp(subtype, SUBTYPE_FLOAT, 16) == 0) { if(chancount == 1 && chanmask == CHANNELS_MONO) channels = ChannelConfig_Mono; else if(chancount == 2 && chanmask == CHANNELS_STEREO) channels = ChannelConfig_Stereo; else if(chancount == 4 && chanmask == CHANNELS_QUAD) channels = ChannelConfig_Quad; else if(chancount == 6 && (chanmask == CHANNELS_5DOT1 || chanmask == CHANNELS_5DOT1_REAR)) channels = ChannelConfig_X51; else if(chancount == 7 && chanmask == CHANNELS_6DOT1) channels = ChannelConfig_X61; else if(chancount == 8 && chanmask == CHANNELS_7DOT1) channels = ChannelConfig_X71; else goto next_chunk; } if(memcmp(subtype, SUBTYPE_PCM, 16) == 0 || memcmp(subtype, SUBTYPE_BFORMAT_PCM, 16) == 0) { if(bitdepth == 8) type = SampleType_UInt8; else if(bitdepth == 16) type = SampleType_Int16; else goto next_chunk; } else if(memcmp(subtype, SUBTYPE_FLOAT, 16) == 0 || memcmp(subtype, SUBTYPE_BFORMAT_FLOAT, 16) == 0) { if(bitdepth == 32) type = SampleType_Float32; else goto next_chunk; } else goto next_chunk; } else goto next_chunk; framesize = FramesToBytes(1, channels, type); /* Calculate the number of frames per block (ADPCM will need extra * consideration). */ framealign = blockalign / framesize; } else if(memcmp(tag, "smpl", 4) == 0) { /* sampler data needs at least 36 bytes */ if(size < 36) goto next_chunk; /* Most of this only affects MIDI sampling, but we only care about * the loop definitions at the end. */ /*ALuint manufacturer =*/ read_le32(*file); /*ALuint product =*/ read_le32(*file); /*ALuint smpperiod =*/ read_le32(*file); /*ALuint unitynote =*/ read_le32(*file); /*ALuint pitchfrac =*/ read_le32(*file); /*ALuint smptefmt =*/ read_le32(*file); /*ALuint smpteoffset =*/ read_le32(*file); ALuint loopcount = read_le32(*file); /*ALuint extrabytes =*/ read_le32(*file); size -= 36; for(ALuint i = 0;i < loopcount && size >= 24;++i) { /*ALuint id =*/ read_le32(*file); ALuint type = read_le32(*file); ALuint loopstart = read_le32(*file); ALuint loopend = read_le32(*file); /*ALuint frac =*/ read_le32(*file); ALuint numloops = read_le32(*file); size -= 24; /* Only handle indefinite forward loops. */ if(type == 0 || numloops == 0) { loop_pts[0] = loopstart; loop_pts[1] = loopend; break; } } } else if(memcmp(tag, "data", 4) == 0) { if(framesize == 0) goto next_chunk; /* Make sure there's at least one sample frame of audio data. */ std::istream::pos_type start = file->tellg(); std::istream::pos_type end = start + std::istream::pos_type(size - (size%framesize)); if(end-start >= framesize) { /* Loop points are byte offsets relative to the data start. * Convert to sample frame offsets. */ return SharedPtr<Decoder>(new WaveDecoder(file, channels, type, frequency, framesize, start, end, loop_pts[0] / blockalign * framealign, loop_pts[1] / blockalign * framealign )); } } next_chunk: if(size > 0) file->ignore(size); } return SharedPtr<Decoder>(nullptr); }
static jack_default_audio_sample_t read_sample_le16(const char *buffer) { int16_t s = (int16_t)read_le16(buffer); uint16_t upper_bound = (uint16_t)INT16_MAX + (s <= 0); return (jack_default_audio_sample_t)s / (jack_default_audio_sample_t)upper_bound; }
static jack_default_audio_sample_t read_sample_le16u(const char *buffer) { uint32_t u = read_le16(buffer); return (((jack_default_audio_sample_t) u) / ((jack_default_audio_sample_t) UINT16_MAX)) * 2.0 - 2.0; }
static void Zone_read(Zone *self, Reader *stream) { self->mGenIdx = read_le16(stream); self->mModIdx = read_le16(stream); }
static void Generator_read(Generator *self, Reader *stream) { self->mGenerator = read_le16(stream); self->mAmount = read_le16(stream); }
static void InstrumentHeader_read(InstrumentHeader *self, Reader *stream) { Reader_read(stream, self->mName, sizeof(self->mName)); self->mZoneIdx = read_le16(stream); }