sf_count_t SndFileDecoder::file_seek(sf_count_t offset, int whence, void *user_data) { FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader; if(reader->Seek((long)offset, whence) != 0) return -1; return reader->Tell(); }
bool Init(const String& path) { File file; if(!file.OpenRead(path)) return false; FileReader stream = FileReader(file); WavHeader riff; stream << riff; if(riff != "RIFF") return false; char riffType[4]; stream.SerializeObject(riffType); if(strncmp(riffType, "WAVE", 4) != 0) return false; while(stream.Tell() < stream.GetSize()) { WavHeader chunkHdr; stream << chunkHdr; if(chunkHdr == "fmt ") { stream << m_format; //Logf("Sample format: %s", Logger::Info, (m_format.nFormat == 1) ? "PCM" : "Unknown"); //Logf("Channels: %d", Logger::Info, m_format.nChannels); //Logf("Sample rate: %d", Logger::Info, m_format.nSampleRate); //Logf("Bps: %d", Logger::Info, m_format.nBitsPerSample); } else if(chunkHdr == "data") // data Chunk { // validate header if(m_format.nFormat != 1) return false; if(m_format.nChannels > 2 || m_format.nChannels == 0) return false; if(m_format.nBitsPerSample != 16) return false; // Read data m_length = chunkHdr.nLength / sizeof(short); m_pcm.resize(chunkHdr.nLength); stream.Serialize(m_pcm.data(), chunkHdr.nLength); } else { stream.Skip(chunkHdr.nLength); } } // Calculate the sample step if the rate is not the same as the output rate double sampleStep = (double)m_format.nSampleRate / (double)m_audio->GetSampleRate(); m_sampleStepIncrement = (uint64)(sampleStep * (double)fp_sampleStep); return true; }
off_t MPG123Decoder::file_lseek(void *handle, off_t offset, int whence) { FileReader *reader = reinterpret_cast<MPG123Decoder*>(handle)->Reader; if(whence == SEEK_CUR) { if(offset < 0 && reader->Tell()+offset < 0) return -1; } else if(whence == SEEK_END) { if(offset < 0 && reader->GetLength()+offset < 0) return -1; } if(reader->Seek(offset, whence) != 0) return -1; return reader->Tell(); }
off_t MPG123Decoder::file_lseek(void *handle, off_t offset, int whence) { MPG123Decoder *self = reinterpret_cast<MPG123Decoder*>(handle); FileReader *reader = self->Reader; if(whence == SEEK_SET) offset += self->StartOffset; else if(whence == SEEK_CUR) { if(offset < 0 && reader->Tell()+offset < self->StartOffset) return -1; } else if(whence == SEEK_END) { if(offset < 0 && reader->GetLength()+offset < self->StartOffset) return -1; } if(reader->Seek(offset, whence) != 0) return -1; return reader->Tell() - self->StartOffset; }
virtual char *Gets(char *strbuf, int len) { if (len <= 0 || FilePos >= StartPos + Length) return NULL; char *p = mReader->Gets(strbuf, len); if (p != NULL) { int old = FilePos; FilePos = (long)mReader->Tell(); if (FilePos - StartPos > Length) { strbuf[Length - old + StartPos] = 0; } } return p; }
virtual long Seek(long offset, int origin) { switch (origin) { case SEEK_SET: offset += StartPos; break; case SEEK_END: offset += StartPos + Length; break; case SEEK_CUR: offset += (long)mReader->Tell(); break; } if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope if (mReader->Seek(offset, FileReader::SeekSet) == 0) { FilePos = offset; return 0; } return -1; }
FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height, uint8_t depth, uint8_t colortype, uint8_t interlace) : FTexture(NULL, lumpnum), SourceFile(filename), Pixels(0), Spans(0), BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false), PaletteMap(0), PaletteSize(0), StartOfIDAT(0) { union { uint32_t palette[256]; uint8_t pngpal[256][3]; } p; uint8_t trans[256]; uint32_t len, id; int i; if (lumpnum == -1) fr = &lump; else fr = nullptr; UseType = TEX_MiscPatch; LeftOffset = 0; TopOffset = 0; bMasked = false; Width = width; Height = height; CalcBitSize (); memset(trans, 255, 256); // Parse pre-IDAT chunks. I skip the CRCs. Is that bad? lump.Seek(33, SEEK_SET); lump.Read(&len, 4); lump.Read(&id, 4); while (id != MAKE_ID('I','D','A','T') && id != MAKE_ID('I','E','N','D')) { len = BigLong((unsigned int)len); switch (id) { default: lump.Seek (len, SEEK_CUR); break; case MAKE_ID('g','r','A','b'): // This is like GRAB found in an ILBM, except coordinates use 4 bytes { uint32_t hotx, hoty; int ihotx, ihoty; lump.Read(&hotx, 4); lump.Read(&hoty, 4); ihotx = BigLong((int)hotx); ihoty = BigLong((int)hoty); if (ihotx < -32768 || ihotx > 32767) { Printf ("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", Wads.GetLumpFullName (lumpnum), ihotx, ihotx); ihotx = 0; } if (ihoty < -32768 || ihoty > 32767) { Printf ("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", Wads.GetLumpFullName (lumpnum), ihoty, ihoty); ihoty = 0; } LeftOffset = ihotx; TopOffset = ihoty; } break; case MAKE_ID('P','L','T','E'): PaletteSize = MIN<int> (len / 3, 256); lump.Read (p.pngpal, PaletteSize * 3); if (PaletteSize * 3 != (int)len) { lump.Seek (len - PaletteSize * 3, SEEK_CUR); } for (i = PaletteSize - 1; i >= 0; --i) { p.palette[i] = MAKERGB(p.pngpal[i][0], p.pngpal[i][1], p.pngpal[i][2]); } break; case MAKE_ID('t','R','N','S'): lump.Read (trans, len); HaveTrans = true; // Save for colortype 2 NonPaletteTrans[0] = uint16_t(trans[0] * 256 + trans[1]); NonPaletteTrans[1] = uint16_t(trans[2] * 256 + trans[3]); NonPaletteTrans[2] = uint16_t(trans[4] * 256 + trans[5]); break; case MAKE_ID('a','l','P','h'): bAlphaTexture = true; bMasked = true; break; } lump.Seek(4, SEEK_CUR); // Skip CRC lump.Read(&len, 4); id = MAKE_ID('I','E','N','D'); lump.Read(&id, 4); } StartOfIDAT = lump.Tell() - 8; switch (colortype) { case 4: // Grayscale + Alpha bMasked = true; // intentional fall-through case 0: // Grayscale if (!bAlphaTexture) { if (colortype == 0 && HaveTrans && NonPaletteTrans[0] < 256) { bMasked = true; PaletteSize = 256; PaletteMap = new uint8_t[256]; memcpy (PaletteMap, GrayMap, 256); PaletteMap[NonPaletteTrans[0]] = 0; } else { PaletteMap = GrayMap; } } break; case 3: // Paletted PaletteMap = new uint8_t[PaletteSize]; GPalette.MakeRemap (p.palette, PaletteMap, trans, PaletteSize); for (i = 0; i < PaletteSize; ++i) { if (trans[i] == 0) { bMasked = true; PaletteMap[i] = 0; } } break; case 6: // RGB + Alpha bMasked = true; break; case 2: // RGB bMasked = HaveTrans; break; } }
sf_count_t SndFileDecoder::file_tell(void *user_data) { FileReader *reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader; return reader->Tell(); }
FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height, BYTE depth, BYTE colortype, BYTE interlace) : FTexture(NULL, lumpnum), SourceFile(filename), Pixels(0), Spans(0), BitDepth(depth), ColorType(colortype), Interlace(interlace), PaletteMap(0), PaletteSize(0), StartOfIDAT(0) { union { DWORD palette[256]; BYTE pngpal[256][3]; }; BYTE trans[256]; bool havetRNS = false; DWORD len, id; int i; UseType = TEX_MiscPatch; LeftOffset = 0; TopOffset = 0; bMasked = false; Width = width; Height = height; CalcBitSize (); memset (trans, 255, 256); // Parse pre-IDAT chunks. I skip the CRCs. Is that bad? lump.Seek (33, SEEK_SET); lump >> len >> id; while (id != MAKE_ID('I','D','A','T') && id != MAKE_ID('I','E','N','D')) { len = BigLong((unsigned int)len); switch (id) { default: lump.Seek (len, SEEK_CUR); break; case MAKE_ID('g','r','A','b'): // This is like GRAB found in an ILBM, except coordinates use 4 bytes { DWORD hotx, hoty; int ihotx, ihoty; lump >> hotx >> hoty; ihotx = BigLong((int)hotx); ihoty = BigLong((int)hoty); if (ihotx < -32768 || ihotx > 32767) { Printf ("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", Wads.GetLumpFullName (lumpnum), ihotx, ihotx); ihotx = 0; } if (ihoty < -32768 || ihoty > 32767) { Printf ("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", Wads.GetLumpFullName (lumpnum), ihoty, ihoty); ihoty = 0; } LeftOffset = (int)ihotx; TopOffset = (int)ihoty; } break; case MAKE_ID('P','L','T','E'): PaletteSize = MIN<int> (len / 3, 256); lump.Read (pngpal, PaletteSize * 3); if (PaletteSize * 3 != (int)len) { lump.Seek (len - PaletteSize * 3, SEEK_CUR); } for (i = PaletteSize - 1; i >= 0; --i) { palette[i] = MAKERGB(pngpal[i][0], pngpal[i][1], pngpal[i][2]); } break; case MAKE_ID('t','R','N','S'): lump.Read (trans, len); havetRNS = true; break; case MAKE_ID('a','l','P','h'): bAlphaTexture = true; bMasked = true; break; } lump >> len >> len; // Skip CRC id = MAKE_ID('I','E','N','D'); lump >> id; } StartOfIDAT = lump.Tell() - 8; switch (colortype) { case 4: // Grayscale + Alpha bMasked = true; // intentional fall-through case 0: // Grayscale if (!bAlphaTexture) { if (colortype == 0 && havetRNS && trans[0] != 0) { bMasked = true; PaletteSize = 256; PaletteMap = new BYTE[256]; memcpy (PaletteMap, GrayMap, 256); PaletteMap[trans[0]] = 0; } else { PaletteMap = GrayMap; } } break; case 3: // Paletted PaletteMap = new BYTE[PaletteSize]; GPalette.MakeRemap (palette, PaletteMap, trans, PaletteSize); for (i = 0; i < PaletteSize; ++i) { if (trans[i] == 0) { bMasked = true; PaletteMap[i] = 0; } } break; case 6: // RGB + Alpha bMasked = true; break; } }