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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 903 - (show annotations) (download)
Sat Jul 22 14:22:53 2006 UTC (17 years, 9 months ago) by persson
File size: 6034 byte(s)
* real support for 24 bit samples - samples are not truncated to 16
  bits anymore
* support for aftertouch (channel pressure, not polyphonic aftertouch)

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 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 #include "Stream.h"
25
26 namespace LinuxSampler { namespace gig {
27
28 uint Stream::UnusedStreams = 0;
29 uint Stream::TotalStreams = 0;
30
31 /// Returns number of refilled sample points or a value < 0 on error.
32 int Stream::ReadAhead(unsigned long SampleCount) {
33 if (this->State == state_unused) return -1;
34 if (this->State == state_end) return 0;
35 if (!SampleCount) return 0;
36 if (!pRingBuffer->write_space()) return 0;
37
38 ::gig::Sample* pSample = pDimRgn->pSample;
39 long total_readsamples = 0, readsamples = 0;
40 long samplestoread = SampleCount / pSample->Channels;
41 uint8_t* pBuf = pRingBuffer->get_write_ptr();
42 bool endofsamplereached;
43
44 // refill the disk stream buffer
45 if (this->DoLoop) { // honor looping
46 total_readsamples = pSample->ReadAndLoop(pBuf, samplestoread, &this->PlaybackState, pDimRgn, pDecompressionBuffer);
47 endofsamplereached = (this->PlaybackState.position >= pSample->SamplesTotal);
48 dmsg(5,("Refilled stream %d with %d (SamplePos: %d)", this->hThis, total_readsamples, this->PlaybackState.position));
49 }
50 else { // normal forward playback
51
52 pSample->SetPos(this->SampleOffset); // recover old position
53
54 do {
55 readsamples = pSample->Read(&pBuf[total_readsamples * pSample->FrameSize], samplestoread, pDecompressionBuffer);
56 samplestoread -= readsamples;
57 total_readsamples += readsamples;
58 } while (samplestoread && readsamples > 0);
59
60 // we have to store the position within the sample, because other streams might use the same sample
61 this->SampleOffset = pSample->GetPos();
62
63 endofsamplereached = (SampleOffset >= pSample->SamplesTotal);
64 dmsg(5,("Refilled stream %d with %d (SamplePos: %d)", this->hThis, total_readsamples, this->SampleOffset));
65 }
66
67 // we must delay the increment_write_ptr_with_wrap() after the while() loop because we need to
68 // ensure that we read exactly SampleCount sample, otherwise the buffer wrapping code will fail
69 pRingBuffer->increment_write_ptr_with_wrap(total_readsamples * pSample->FrameSize);
70
71 // update stream state
72 if (endofsamplereached) SetState(state_end);
73 else SetState(state_active);
74
75 return total_readsamples;
76 }
77
78 void Stream::WriteSilence(unsigned long SilenceSampleWords) {
79 memset(pRingBuffer->get_write_ptr(), 0, SilenceSampleWords * BytesPerSample);
80 pRingBuffer->increment_write_ptr_with_wrap(SilenceSampleWords * BytesPerSample);
81 }
82
83 Stream::Stream( ::gig::buffer_t* pDecompressionBuffer, uint BufferSize, uint BufferWrapElements) {
84 this->pExportReference = NULL;
85 this->State = state_unused;
86 this->hThis = 0;
87 this->pDimRgn = NULL;
88 this->SampleOffset = 0;
89 this->PlaybackState.position = 0;
90 this->PlaybackState.reverse = false;
91 this->pRingBuffer = new RingBuffer<uint8_t>(BufferSize * 3, BufferWrapElements * 3);
92 this->pDecompressionBuffer = pDecompressionBuffer;
93 UnusedStreams++;
94 TotalStreams++;
95 }
96
97 Stream::~Stream() {
98 Reset();
99 if (pRingBuffer) delete pRingBuffer;
100 UnusedStreams--;
101 TotalStreams--;
102 }
103
104 /// Called by disk thread to activate the disk stream.
105 void Stream::Launch(Stream::Handle hStream, reference_t* pExportReference, ::gig::DimensionRegion* pDimRgn, unsigned long SampleOffset, bool DoLoop) {
106 UnusedStreams--;
107 this->pExportReference = pExportReference;
108 this->hThis = hStream;
109 this->pDimRgn = pDimRgn;
110 this->SampleOffset = SampleOffset;
111 this->PlaybackState.position = SampleOffset;
112 this->PlaybackState.reverse = false;
113 this->PlaybackState.loop_cycles_left = pDimRgn->pSample->LoopPlayCount;
114 this->DoLoop = DoLoop;
115 BytesPerSample = pDimRgn->pSample->BitDepth / 8;
116 SetState(state_active);
117 }
118
119 }} // namespace LinuxSampler::gig

  ViewVC Help
Powered by ViewVC