/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * instrumentparser.cc * * Wed Mar 9 13:22:24 CET 2011 * Copyright 2011 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of DrumGizmo. * * DrumGizmo is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * DrumGizmo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "instrumentparser.h" #include #include #include #include "cpp11fix.h" #include "path.h" #include "nolocale.h" InstrumentParser::InstrumentParser(Instrument& instrument) : instrument(instrument) { } int InstrumentParser::parseFile(const std::string& filename) { path = getPath(filename); return SAXParser::parseFile(filename); } void InstrumentParser::startTag(const std::string& name, const attr_t& attr) { if(name == "instrument") { if(attr.find("name") != attr.end()) { instrument._name = attr.at("name"); } if(attr.find("description") != attr.end()) { instrument._description = attr.at("description"); } if(attr.find("version") != attr.end()) { try { instrument.version = VersionStr(attr.at("version")); } catch(const char* err) { ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err); instrument.version = VersionStr(1,0,0); } } else { WARN(instrparser, "Missing version number, assuming 1.0\n"); instrument.version = VersionStr(1,0,0); } } if(name == "samples") { } if(name == "sample") { if(attr.find("name") == attr.end()) { ERR(instrparser,"Missing required attribute 'name'.\n"); return; } float power; if(attr.find("power") == attr.end()) { power = -1; } else { power = atof_nol(attr.at("power").c_str()); DEBUG(instrparser, "Instrument power set to %f\n", power); } // TODO get rid of new or delete it properly sample = new Sample(attr.at("name"), power); } if(name == "audiofile") { if(sample == nullptr) { ERR(instrparser,"Missing Sample!\n"); return; } if(attr.find("file") == attr.end()) { ERR(instrparser,"Missing required attribute 'file'.\n"); return; } if(attr.find("channel") == attr.end()) { ERR(instrparser,"Missing required attribute 'channel'.\n"); return; } int filechannel = 1; // default, override with optional attribute if(attr.find("filechannel") != attr.end()) { filechannel = std::stoi(attr.at("filechannel")); if(filechannel < 1) { ERR(instrparser,"Invalid value for attribute 'filechannel'.\n"); filechannel = 1; } } filechannel = filechannel - 1; // 1-based in file but zero-based internally. auto audio_file = std::make_unique(path + "/" + attr.at("file"), filechannel); // note: memory leak! the channels are never released // once I replaced this using unique_ptr, the channels were // destroyed when the InstrumentParser went out of scope // (see drumkitparser.cc, where the InstrumentParser lives in // local scope). // so.. we cannot replace this using smart ptr until we decided // the ownership semantics for instances InstrumentChannel InstrumentChannel *instrument_channel = new InstrumentChannel(attr.at("channel")); channellist.push_back(instrument_channel); sample->addAudioFile(instrument_channel, audio_file.get()); // Transfer audio_file ownership to the instrument. instrument.audiofiles.push_back(std::move(audio_file)); } if(name == "velocities") { } if(name == "velocity") { if(attr.find("lower") == attr.end()) { ERR(instrparser,"Missing required attribute 'lower'.\n"); return; } if(attr.find("upper") == attr.end()) { ERR(instrparser,"Missing required attribute 'upper'.\n"); return; } lower = atof_nol(attr.at("lower").c_str()); upper = atof_nol(attr.at("upper").c_str()); } if(name == "sampleref") { if(attr.find("name") == attr.end()) { ERR(instrparser,"Missing required attribute 'name'.\n"); return; } Sample* sample_ref = nullptr; for(auto& sample : instrument.samplelist) { if(sample->name == attr.at("name")) { sample_ref = sample; break; } } if(sample_ref == nullptr) { ERR(instrparser,"Samplref pointed at non-existing sample.\n"); return; } if(instrument.version == VersionStr("1.0")) { // Old "velocity group" algorithm needs this instrument.addSample(lower, upper, sample_ref); } } } void InstrumentParser::endTag(const std::string& name) { if(name == "sample") { if(sample == nullptr) { ERR(instrparser,"Missing Sample.\n"); return; } instrument.samplelist.push_back(sample); sample = nullptr; } if(name == "instrument") { instrument.finalise(); } }