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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 393 - (hide annotations) (download)
Sun Feb 20 12:30:36 2005 UTC (19 years, 2 months ago) by persson
File size: 5843 byte(s)
* fixed a bug that caused noise at end of samples

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

  ViewVC Help
Powered by ViewVC