#ifndef OGG_H #define OGG_H /* * @(#)Ogg.h * * This file is part of webCDwriter - Network CD Writing. * * Copyright (C) 2003 Jörg P. M. Haeger * * webCDwriter is free software. See CDWserver.cpp for details. */ #include "File.h" #include "FileInputStream.h" /** * A class to handle ogg files. * * @version 20030220 * @author Jörg P. M. Haeger */ class Ogg { private: int audio_channels; int audio_sample_rate; long dataLength; long headerStart; int64 sampleNum; int vorbis_version; public: Ogg(File &file) { dataLength = File(file).length(); FileInputStream inStream = new FileInputStream(file); int pos = 0; while (true) { int packet_type = 0; char capture_pattern1[] = { 'v', 'o', 'r', 'b', 'i', 's' }; for (int i = 0; capture_pattern1[i] != 0; i++) { int b = inStream.read(); if (b == -1) throw new Exception( "no Vorbis identification header"); pos++; if (b != capture_pattern1[i]) { packet_type = b; i = -1; } } if (packet_type == 1) break; } vorbis_version = read32Bits(inStream); if (vorbis_version > 0) throw new Exception(S.e + "unknown vorbis_version " + vorbis_version); audio_channels = inStream.read(); audio_sample_rate = read32Bits(inStream); pos += 4 + 1 + 4; headerStart = dataLength - 16 * 1024; inStream.skip(headerStart - pos); int count = 0; while (true) { char capture_pattern[] = { 'O', 'g', 'g', 'S', 0 }; int capture_pattern_length = strlen(capture_pattern) + 1; int i; for (i = 0; i < capture_pattern_length; i++) { int b = inStream.read(); if (b == -1) break; if (b != capture_pattern[i]) { headerStart += i + 1; i = -1; } } if (i < capture_pattern_length) break; count++; int header_type_flag = inStream.read(); if (header_type_flag == -1) break; int64 absolute_granule_position = 0; for (i = 0; i < 8; i++) { int64 b = inStream.read(); if (b == -1) break; absolute_granule_position |= b << (8 * i); } if (i < 8) break; if ((header_type_flag & 0x06) != 0) sampleNum = absolute_granule_position; } } long getSeconds() { if (audio_sample_rate > 0) return sampleNum / audio_sample_rate; else return 0; } int read32Bits(FileInputStream &inStream) { int n = 0; for (int i = 0; i < 4; i++) { int b = inStream.read(); if (b == -1) throw new Exception("Unexpected end of input stream"); n |= b << (8 * i); } return n; } }; #endif