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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1484 - (hide annotations) (download) (as text)
Thu Nov 15 13:24:41 2007 UTC (16 years, 6 months ago) by senoner
File MIME type: text/x-c++hdr
File size: 8526 byte(s)
* Stream.h: added a missing divide by BytesPerSample in GetWriteSpace()
* since this function is currently only used in the stream's
* qsort() compare function, it did trigger any bugs
* Resampler.h, Synthesizer.h:
* cubic interpolation now works in 24bit mode too
* faster method to read 24bit words on little endian machines (x86):
*  replaced 3 byte reads + shifts with a 1 unaligned 32bit read and shift

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 1321 * Copyright (C) 2005 - 2007 Christian Schoenebeck *
7 schoenebeck 53 * *
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 schoenebeck 505 #include <gig.h>
30    
31 schoenebeck 53 #include "../../common/RingBuffer.h"
32    
33     namespace LinuxSampler { namespace gig {
34    
35 schoenebeck 563 /** @brief Buffered Disk Stream
36     *
37     * This encapsulation of a disk stream uses a ring buffer to allow
38     * thread safe refilling the stream's buffer with one thread (disk
39     * thread) and actual use / extraction of the audio data from the
40     * stream's buffer with another thread (audio thread).
41     */
42 schoenebeck 53 class Stream {
43     public:
44     // Member Types
45     typedef uint32_t OrderID_t;
46     typedef uint32_t Handle; ///< unique identifier of a relationship between one stream and a consumer (Voice)
47 schoenebeck 1321 enum { INVALID_HANDLE = 0 };
48 schoenebeck 53 enum state_t { ///< streams go through severe cyclic state transition (unused->active->end->unused->...)
49     state_unused, ///< stream is not in use, thus can still be launched
50     state_active, ///< stream provides data in it's buffer to be read and hasn't reached the end yet (this is the usual case)
51     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)
52     };
53     struct reference_t { ///< Defines the current relationship between the stream and a client (voice).
54     OrderID_t OrderID; ///< Unique identifier that identifies the creation order of a stream requested by a voice.
55     Handle hStream; ///< Unique identifier of the relationship between stream and client.
56     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).
57     Stream* pStream; ///< Points to the assigned and activated stream or is NULL if the disk thread hasn't launched a stream yet.
58     };
59    
60     // Methods
61 schoenebeck 385 Stream( ::gig::buffer_t* pDecompressionBuffer, uint BufferSize, uint BufferWrapElements);
62 letz 502 virtual ~Stream();
63 schoenebeck 53 int ReadAhead(unsigned long SampleCount);
64     void WriteSilence(unsigned long SilenceSampleWords);
65    
66     inline int GetReadSpace() {
67 persson 903 return (pRingBuffer && State != state_unused) ? pRingBuffer->read_space() / BytesPerSample : 0;
68 schoenebeck 53 }
69    
70     inline int GetWriteSpace() {
71 senoner 1484 return (pRingBuffer && State == state_active) ? pRingBuffer->write_space() / BytesPerSample : 0;
72 schoenebeck 53 }
73    
74     inline int GetWriteSpaceToEnd() {
75 persson 903 return (pRingBuffer && State == state_active) ? pRingBuffer->write_space_to_end_with_wrap() / BytesPerSample : 0;
76 schoenebeck 53 }
77    
78     // adjusts the write space to avoid buffer boundaries which would lead to the wrap space
79     // within the buffer (needed for interpolation) getting filled only partially
80     // for more infos see the docs in ringbuffer.h at adjust_write_space_to_avoid_boundary()
81     inline int AdjustWriteSpaceToAvoidBoundary(int cnt, int capped_cnt) {
82 persson 903 return pRingBuffer->adjust_write_space_to_avoid_boundary(cnt * BytesPerSample, capped_cnt * BytesPerSample) / BytesPerSample;
83 schoenebeck 53 }
84    
85     // gets the current read_ptr within the ringbuffer
86 persson 903 inline uint8_t* GetReadPtr(void) {
87 schoenebeck 53 return pRingBuffer->get_read_ptr();
88     }
89    
90     inline void IncrementReadPos(uint Count) {
91 persson 903 Count *= BytesPerSample;
92 schoenebeck 53 uint leftspace = pRingBuffer->read_space();
93     pRingBuffer->increment_read_ptr(Min(Count, leftspace));
94     if (State == state_end && Count >= leftspace) {
95     Reset(); // quit relation between consumer (voice) and stream and reset stream right after
96     }
97     }
98    
99     // Static Method
100     inline static uint GetUnusedStreams() { return UnusedStreams; }
101     protected:
102     // Methods
103 persson 865 void Launch(Stream::Handle hStream, reference_t* pExportReference, ::gig::DimensionRegion* pDimRgn, unsigned long SampleOffset, bool DoLoop);
104 schoenebeck 53 inline void Kill() { pExportReference = NULL; Reset(); } ///< Will be called by disk thread after a 'deletion' command from the audio thread (within the voice class)
105     inline Stream::Handle GetHandle() { return hThis; }
106     inline Stream::state_t GetState() { return State; }
107     friend class DiskThread; // only the disk thread should be able to launch and most important kill a disk stream to avoid race conditions
108     private:
109     // Attributes
110     reference_t* pExportReference;
111     state_t State;
112     Stream::Handle hThis;
113     unsigned long SampleOffset;
114 persson 865 ::gig::DimensionRegion* pDimRgn;
115 schoenebeck 53 ::gig::playback_state_t PlaybackState;
116 schoenebeck 970 RingBuffer<uint8_t,false>* pRingBuffer;
117 schoenebeck 53 bool DoLoop;
118 schoenebeck 385 ::gig::buffer_t* pDecompressionBuffer;
119 persson 903 int BytesPerSample;
120 schoenebeck 53
121     // Static Attributes
122     static uint UnusedStreams; //< Reflects how many stream objects of all stream instances are currently not in use.
123 senkov 333 static uint TotalStreams; //< Reflects how many stream objects currently exist.
124 schoenebeck 53
125     // Methods
126     inline void Reset() {
127     SampleOffset = 0;
128 persson 865 pDimRgn = NULL;
129 schoenebeck 53 PlaybackState.position = 0;
130     PlaybackState.reverse = false;
131     hThis = 0;
132     pRingBuffer->init(); // reset ringbuffer
133     if (State != state_unused) {
134     // we can't do 'SetPos(state_unused)' here, due to possible race conditions)
135     if (pExportReference) {
136     pExportReference->State = state_unused;
137     pExportReference = NULL;
138     }
139     State = state_unused;
140     UnusedStreams++;
141     }
142     }
143     inline void SetState(state_t State) {
144     if (pExportReference) pExportReference->State = State;
145     this->State = State;
146     }
147     inline long Min(long a, long b) { return (a < b) ? a : b; }
148     };
149    
150     }} // namespace LinuxSampler::gig
151    
152     #endif // __LS_GIG_STREAM_H__

  ViewVC Help
Powered by ViewVC