/[svn]/linuxsampler/trunk/src/engines/sf2/EngineChannel.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/sf2/EngineChannel.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2012 - (hide annotations) (download)
Fri Oct 23 17:53:17 2009 UTC (14 years, 5 months ago) by iliev
File size: 6654 byte(s)
* Refactoring: moved the independent code from
  the Gigasampler format engine to base classes
* SFZ format engine: experimental code (not usable yet)
* SoundFont format engine: experimental code (not usable yet)
* Fixed crash which may occur when MIDI key + transpose is out of range

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6     * Copyright (C) 2005-2009 Christian Schoenebeck *
7     * Copyright (C) 2009 Grigor Iliev *
8     * *
9     * This program is free software; you can redistribute it and/or modify *
10     * it under the terms of the GNU General Public License as published by *
11     * the Free Software Foundation; either version 2 of the License, or *
12     * (at your option) any later version. *
13     * *
14     * This program is distributed in the hope that it will be useful, *
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17     * GNU General Public License for more details. *
18     * *
19     * You should have received a copy of the GNU General Public License *
20     * along with this program; if not, write to the Free Software *
21     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
22     * MA 02111-1307 USA *
23     ***************************************************************************/
24    
25     #include "EngineChannel.h"
26     #include "Engine.h"
27    
28     namespace LinuxSampler { namespace sf2 {
29     EngineChannel::EngineChannel() {
30     for(int i = 0; i < 128; i++) PressedKeys[i] = false;
31     LastKey = LastKeySwitch = -1;
32     }
33    
34     EngineChannel::~EngineChannel() {
35     DisconnectAudioOutputDevice();
36     // In case the channel was removed before the instrument was
37     // fully loaded, try to give back instrument again (see bug #113)
38     InstrumentChangeCmd< ::sf2::Region, ::sf2::InstrumentBase>& cmd = ChangeInstrument(NULL);
39     if (cmd.pInstrument) {
40     InstrumentResourceManager* instrs = dynamic_cast<InstrumentResourceManager*>(pEngine->GetInstrumentManager());
41     instrs->HandBack(cmd.pInstrument, this);
42     }
43     ///////
44     }
45    
46     AbstractEngine::Format EngineChannel::GetEngineFormat() { return AbstractEngine::SF2; }
47    
48     /** This method is not thread safe! */
49     void EngineChannel::ResetInternal() {
50     CurrentKeyDimension = 0;
51     EngineChannelBase<Voice, ::sf2::Region, ::sf2::InstrumentBase>::ResetInternal();
52     for(int i = 0; i < 128; i++) PressedKeys[i] = false;
53     }
54    
55     /**
56     * Will be called by the MIDIIn Thread to signal that a program
57     * change should be performed. As a program change isn't
58     * real-time safe, the actual change is performed by the disk
59     * thread.
60     *
61     * @param Program - MIDI program change number
62     */
63     void EngineChannel::SendProgramChange(uint8_t Program) {
64     Engine* engine = dynamic_cast<Engine*>(pEngine);
65     if(engine == NULL) return;
66    
67     if(engine->GetDiskThread()) {
68     engine->GetDiskThread()->OrderProgramChange(Program, this);
69     } else {
70     // TODO:
71     }
72     }
73    
74     /**
75     * Load an instrument from a .sf2 file. PrepareLoadInstrument() has to
76     * be called first to provide the information which instrument to load.
77     * This method will then actually start to load the instrument and block
78     * the calling thread until loading was completed.
79     *
80     * @see PrepareLoadInstrument()
81     */
82     void EngineChannel::LoadInstrument() {
83     InstrumentResourceManager* pInstrumentManager = dynamic_cast<InstrumentResourceManager*>(pEngine->GetInstrumentManager());
84    
85     // make sure we don't trigger any new notes with an old
86     // instrument
87     InstrumentChangeCmd< ::sf2::Region, ::sf2::InstrumentBase>& cmd = ChangeInstrument(0);
88     if (cmd.pInstrument) {
89     // give old instrument back to instrument manager, but
90     // keep the dimension regions and samples that are in use
91     pInstrumentManager->HandBackInstrument(cmd.pInstrument, this, cmd.pRegionsInUse);
92     }
93     cmd.pRegionsInUse->clear();
94    
95     // delete all key groups
96     ActiveKeyGroups.clear();
97    
98     // request sf2 instrument from instrument manager
99     ::sf2::InstrumentBase* newInstrument;
100     try {
101     InstrumentManager::instrument_id_t instrid;
102     instrid.FileName = InstrumentFile;
103     instrid.Index = InstrumentIdx;
104    
105     newInstrument = pInstrumentManager->Borrow(instrid, this);
106     if (!newInstrument) {
107     throw InstrumentManagerException("resource was not created");
108     }
109     }
110     catch (InstrumentManagerException e) {
111     InstrumentStat = -3;
112     StatusChanged(true);
113     String msg = "sf2::Engine error: Failed to load instrument, cause: " + e.Message();
114     throw Exception(msg);
115     }
116     catch (::sf2::Exception e) {
117     InstrumentStat = -3;
118     StatusChanged(true);
119     String msg = "sf2::Engine error: Failed to load instrument, cause: " + e.Message;
120     throw Exception(msg);
121     }
122     catch (::std::runtime_error e) {
123     InstrumentStat = -3;
124     StatusChanged(true);
125     String msg = "sf2::Engine error: Failed to load instrument, cause: ";
126     msg += e.what();
127     throw Exception(msg);
128     }
129     catch (...) {
130     InstrumentStat = -4;
131     StatusChanged(true);
132     throw Exception("sf2::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse sf2 file.");
133     }
134    
135     // rebuild ActiveKeyGroups map with key groups of current instrument
136     //for (::gig::Region* pRegion = newInstrument->GetFirstRegion(); pRegion; pRegion = newInstrument->GetNextRegion())
137     // if (pRegion->KeyGroup) ActiveKeyGroups[pRegion->KeyGroup] = NULL;
138     // TODO: ^^^
139    
140     InstrumentIdxName = newInstrument->GetName();
141     InstrumentStat = 100;
142    
143     ChangeInstrument(newInstrument);
144    
145     StatusChanged(true);
146     }
147    
148     void EngineChannel::ProcessKeySwitchChange(int key) { }
149    
150     }} // namespace LinuxSampler::sf2

  ViewVC Help
Powered by ViewVC