/[svn]/linuxsampler/trunk/src/engines/gig/Stream.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/gig/Stream.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1321 - (show annotations) (download) (as text)
Tue Sep 4 01:12:49 2007 UTC (16 years, 7 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 8580 byte(s)
* added highly experimental code for synchronizing instrument editors
  hosted in the sampler's process to safely edit instruments while playing
  without a crash (hopefully) by either suspending single regions wherever
  possible or - if unavoidable - whole engine(s)
* disk thread: queue sizes are now proportional to CONFIG_MAX_STREAMS
  instead of fix values
* removed legacy Makefiles in meanwhile deleted src/lib directory and its
  subdirectories
* bumped version to 0.4.0.7cvs

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2007 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __LS_GIG_STREAM_H__
25 #define __LS_GIG_STREAM_H__
26
27 #include "../../common/global.h"
28
29 #if DEBUG_HEADERS
30 # warning Stream.h included
31 #endif // DEBUG_HEADERS
32
33 #include <gig.h>
34
35 #include "../../common/RingBuffer.h"
36
37 namespace LinuxSampler { namespace gig {
38
39 /** @brief Buffered Disk Stream
40 *
41 * This encapsulation of a disk stream uses a ring buffer to allow
42 * thread safe refilling the stream's buffer with one thread (disk
43 * thread) and actual use / extraction of the audio data from the
44 * stream's buffer with another thread (audio thread).
45 */
46 class Stream {
47 public:
48 // Member Types
49 typedef uint32_t OrderID_t;
50 typedef uint32_t Handle; ///< unique identifier of a relationship between one stream and a consumer (Voice)
51 enum { INVALID_HANDLE = 0 };
52 enum state_t { ///< streams go through severe cyclic state transition (unused->active->end->unused->...)
53 state_unused, ///< stream is not in use, thus can still be launched
54 state_active, ///< stream provides data in it's buffer to be read and hasn't reached the end yet (this is the usual case)
55 state_end ///< stream end reached but still providing data in it's buffer to be read (after the client read all remaining data from the stream buffer, state will change automatically to state_unused)
56 };
57 struct reference_t { ///< Defines the current relationship between the stream and a client (voice).
58 OrderID_t OrderID; ///< Unique identifier that identifies the creation order of a stream requested by a voice.
59 Handle hStream; ///< Unique identifier of the relationship between stream and client.
60 state_t State; ///< Current state of the stream that will be pretended to the client (the actual state of the stream might differ though, because the stream might already be in use by another client).
61 Stream* pStream; ///< Points to the assigned and activated stream or is NULL if the disk thread hasn't launched a stream yet.
62 };
63
64 // Methods
65 Stream( ::gig::buffer_t* pDecompressionBuffer, uint BufferSize, uint BufferWrapElements);
66 virtual ~Stream();
67 int ReadAhead(unsigned long SampleCount);
68 void WriteSilence(unsigned long SilenceSampleWords);
69
70 inline int GetReadSpace() {
71 return (pRingBuffer && State != state_unused) ? pRingBuffer->read_space() / BytesPerSample : 0;
72 }
73
74 inline int GetWriteSpace() {
75 return (pRingBuffer && State == state_active) ? pRingBuffer->write_space() : 0;
76 }
77
78 inline int GetWriteSpaceToEnd() {
79 return (pRingBuffer && State == state_active) ? pRingBuffer->write_space_to_end_with_wrap() / BytesPerSample : 0;
80 }
81
82 // adjusts the write space to avoid buffer boundaries which would lead to the wrap space
83 // within the buffer (needed for interpolation) getting filled only partially
84 // for more infos see the docs in ringbuffer.h at adjust_write_space_to_avoid_boundary()
85 inline int AdjustWriteSpaceToAvoidBoundary(int cnt, int capped_cnt) {
86 return pRingBuffer->adjust_write_space_to_avoid_boundary(cnt * BytesPerSample, capped_cnt * BytesPerSample) / BytesPerSample;
87 }
88
89 // gets the current read_ptr within the ringbuffer
90 inline uint8_t* GetReadPtr(void) {
91 return pRingBuffer->get_read_ptr();
92 }
93
94 inline void IncrementReadPos(uint Count) {
95 Count *= BytesPerSample;
96 uint leftspace = pRingBuffer->read_space();
97 pRingBuffer->increment_read_ptr(Min(Count, leftspace));
98 if (State == state_end && Count >= leftspace) {
99 Reset(); // quit relation between consumer (voice) and stream and reset stream right after
100 }
101 }
102
103 // Static Method
104 inline static uint GetUnusedStreams() { return UnusedStreams; }
105 protected:
106 // Methods
107 void Launch(Stream::Handle hStream, reference_t* pExportReference, ::gig::DimensionRegion* pDimRgn, unsigned long SampleOffset, bool DoLoop);
108 inline void Kill() { pExportReference = NULL; Reset(); } ///< Will be called by disk thread after a 'deletion' command from the audio thread (within the voice class)
109 inline Stream::Handle GetHandle() { return hThis; }
110 inline Stream::state_t GetState() { return State; }
111 friend class DiskThread; // only the disk thread should be able to launch and most important kill a disk stream to avoid race conditions
112 private:
113 // Attributes
114 reference_t* pExportReference;
115 state_t State;
116 Stream::Handle hThis;
117 unsigned long SampleOffset;
118 ::gig::DimensionRegion* pDimRgn;
119 ::gig::playback_state_t PlaybackState;
120 RingBuffer<uint8_t,false>* pRingBuffer;
121 bool DoLoop;
122 ::gig::buffer_t* pDecompressionBuffer;
123 int BytesPerSample;
124
125 // Static Attributes
126 static uint UnusedStreams; //< Reflects how many stream objects of all stream instances are currently not in use.
127 static uint TotalStreams; //< Reflects how many stream objects currently exist.
128
129 // Methods
130 inline void Reset() {
131 SampleOffset = 0;
132 pDimRgn = NULL;
133 PlaybackState.position = 0;
134 PlaybackState.reverse = false;
135 hThis = 0;
136 pRingBuffer->init(); // reset ringbuffer
137 if (State != state_unused) {
138 // we can't do 'SetPos(state_unused)' here, due to possible race conditions)
139 if (pExportReference) {
140 pExportReference->State = state_unused;
141 pExportReference = NULL;
142 }
143 State = state_unused;
144 UnusedStreams++;
145 }
146 }
147 inline void SetState(state_t State) {
148 if (pExportReference) pExportReference->State = State;
149 this->State = State;
150 }
151 inline long Min(long a, long b) { return (a < b) ? a : b; }
152 };
153
154 }} // namespace LinuxSampler::gig
155
156 #endif // __LS_GIG_STREAM_H__

  ViewVC Help
Powered by ViewVC