/*** This file is part of snapcast Copyright (C) 2014-2019 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #ifndef STREAM_H #define STREAM_H #include "common/queue.h" #include "common/sample_format.hpp" #include "double_buffer.hpp" #include "message/message.hpp" #include "message/pcm_chunk.hpp" #include #include /// Time synchronized audio stream /** * Queue with PCM data. * Returns "online" server-time-synchronized PCM data */ class Stream { public: Stream(const SampleFormat& format); /// Adds PCM data to the queue void addChunk(msg::PcmChunk* chunk); void clearChunks(); /// Get PCM data, which will be played out in "outputBufferDacTime" time /// frame = (num_channels) * (1 sample in bytes) = (2 channels) * (2 bytes (16 bits) per sample) = 4 bytes (32 bits) bool getPlayerChunk(void* outputBuffer, const chronos::usec& outputBufferDacTime, unsigned long framesPerBuffer); /// "Server buffer": playout latency, e.g. 1000ms void setBufferLen(size_t bufferLenMs); const SampleFormat& getFormat() const { return format_; } bool waitForChunk(size_t ms) const; private: chronos::time_point_clk getNextPlayerChunk(void* outputBuffer, const chronos::usec& timeout, unsigned long framesPerBuffer); chronos::time_point_clk getNextPlayerChunk(void* outputBuffer, const chronos::usec& timeout, unsigned long framesPerBuffer, long framesCorrection); chronos::time_point_clk getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer); chronos::time_point_clk seek(long ms); // time_point_ms seekTo(const time_point_ms& to); void updateBuffers(int age); void resetBuffers(); void setRealSampleRate(double sampleRate); SampleFormat format_; chronos::usec sleep_; Queue> chunks_; // DoubleBuffer cardBuffer; DoubleBuffer miniBuffer_; DoubleBuffer buffer_; DoubleBuffer shortBuffer_; std::shared_ptr chunk_; int median_; int shortMedian_; time_t lastUpdate_; unsigned long playedFrames_; long correctAfterXFrames_; chronos::msec bufferMs_; }; #endif