MuseScore/zerberus/instrument.cpp

196 lines
5.7 KiB
C++

//=============================================================================
// Zerberus
// Zample player
//
// Copyright (C) 2013 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include <stdio.h>
#include <math.h>
#include <QFile>
#include <QFileInfo>
#include <QStringList>
#include "libmscore/xml.h"
#include "audiofile/audiofile.h"
#include "thirdparty/qzip/qzipreader_p.h"
#include "instrument.h"
#include "zone.h"
#include "sample.h"
QByteArray ZInstrument::buf;
int ZInstrument::idx;
//---------------------------------------------------------
// Sample
//---------------------------------------------------------
Sample::~Sample()
{
delete _data;
}
//---------------------------------------------------------
// readSample
//---------------------------------------------------------
Sample* ZInstrument::readSample(const QString& s, MQZipReader* uz)
{
if (uz) {
QList<MQZipReader::FileInfo> fi = uz->fileInfoList();
buf = uz->fileData(s);
if (buf.isEmpty()) {
printf("Sample::read: cannot read sample data <%s>\n", qPrintable(s));
return 0;
}
}
else {
QFile f(s);
if (!f.open(QIODevice::ReadOnly)) {
printf("Sample::read: open <%s> failed\n", qPrintable(s));
return 0;
}
buf = f.readAll();
}
AudioFile a;
if (!a.open(buf)) {
printf("open <%s> failed: %s\n", qPrintable(s), a.error());
return 0;
}
int channel = a.channels();
int frames = a.frames();
int sr = a.samplerate();
short* data = new short[(frames + 3) * channel];
Sample* sa = new Sample(channel, data, frames, sr);
if (frames != a.read(data + channel, frames)) {
printf("Sample read failed: %s\n", a.error());
delete[] data;
delete sa;
sa = 0;
}
for (int i = 0; i < channel; ++i) {
data[i] = data[channel + i];
data[(frames-1) * channel + i] = data[(frames-3) * channel + i];
data[(frames-2) * channel + i] = data[(frames-3) * channel + i];
}
return sa;
}
//---------------------------------------------------------
// ZInstrument
//---------------------------------------------------------
ZInstrument::ZInstrument(Zerberus* z)
{
zerberus = z;
_program = -1;
_refCount = 0;
}
//---------------------------------------------------------
// ZInstrument
//---------------------------------------------------------
ZInstrument::~ZInstrument()
{
for (Zone* z : _zones)
delete z;
}
//---------------------------------------------------------
// load
// return true on success
//---------------------------------------------------------
bool ZInstrument::load(const QString& path)
{
instrumentPath = path;
QFileInfo fi(path);
_name = fi.baseName();
if (fi.isFile())
return loadFromFile(path);
if (fi.isDir())
return loadFromDir(path);
return false;
}
//---------------------------------------------------------
// loadFromDir
//---------------------------------------------------------
bool ZInstrument::loadFromDir(const QString& s)
{
QFile f(s + "/orchestra.xml");
if (!f.open(QIODevice::ReadOnly)) {
printf("cannot load orchestra.xml in <%s>\n", qPrintable(s));
return false;
}
QByteArray buf = f.readAll();
if (buf.isEmpty()) {
printf("Instrument::loadFromFile: orchestra.xml is empty\n");
return false;
}
return read(buf, 0, s);
}
//---------------------------------------------------------
// loadFromFile
//---------------------------------------------------------
bool ZInstrument::loadFromFile(const QString& path)
{
if (path.endsWith(".sfz"))
return loadSfz(path);
if (!path.endsWith(".msoz")) {
printf("<%s> not a orchestra file\n", qPrintable(path));
return false;
}
MQZipReader uz(path);
if (!uz.exists()) {
printf("Instrument::load: %s not found\n", qPrintable(path));
return false;
}
QByteArray buf = uz.fileData("orchestra.xml");
if (buf.isEmpty()) {
printf("Instrument::loadFromFile: orchestra.xml not found\n");
return false;
}
return read(buf, &uz, QString());
}
//---------------------------------------------------------
// read
// read orchestra
//---------------------------------------------------------
bool ZInstrument::read(const QByteArray& buf, MQZipReader* /*uz*/, const QString& /*path*/)
{
Ms::XmlReader e(buf);
while (e.readNextStartElement()) {
if (e.name() == "MuseSynth") {
while (e.readNextStartElement()) {
if (e.name() == "Instrument") {
// if (!read(e, uz, path))
// return false;
}
else
e.unknown();
}
}
else
e.unknown();
}
return true;
}