Blob Blame Raw


#include "toonz/txshsoundlevel.h"
#include "tsound_io.h"
#include "toonz/toonzscene.h"
#include "toonz/sceneproperties.h"
#include "toonz/txshleveltypes.h"

#include "tstream.h"
#include "toutputproperties.h"
#include "tconvert.h"

//-----------------------------------------------------------------------------

DEFINE_CLASS_CODE(TXshSoundLevel, 53)

PERSIST_IDENTIFIER(TXshSoundLevel, "soundLevel")

//=============================================================================

TXshSoundLevel::TXshSoundLevel(std::wstring name, int startOffset, int endOffset)
	: TXshLevel(m_classCode, name), m_soundTrack(0), m_duration(0), m_samplePerFrame(0), m_frameSoundCount(0), m_fps(12), m_path()
{
}

//-----------------------------------------------------------------------------

TXshSoundLevel::~TXshSoundLevel()
{
}

//-----------------------------------------------------------------------------

TXshSoundLevel *TXshSoundLevel::clone() const
{
	TXshSoundLevel *sound = new TXshSoundLevel();
	sound->setSoundTrack(m_soundTrack->clone());
	sound->m_duration = m_duration;
	sound->m_path = m_path;
	sound->m_samplePerFrame = m_samplePerFrame;
	sound->m_frameSoundCount = m_frameSoundCount;
	sound->m_fps = m_fps;
	return sound;
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::setScene(ToonzScene *scene)
{
	assert(scene);
	TXshLevel::setScene(scene);
	TOutputProperties *properties = scene->getProperties()->getOutputProperties();
	assert(properties);
	setFrameRate(properties->getFrameRate());
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::loadSoundTrack()
{
	assert(getScene());

	TSceneProperties *properties = getScene()->getProperties();
	if (properties) {
		TOutputProperties *outputProperties = properties->getOutputProperties();
		if (outputProperties)
			m_fps = outputProperties->getFrameRate();
	}
	TFilePath path = getScene()->decodeFilePath(m_path);
	try {
		loadSoundTrack(path);
	} catch (TException &e) {
		throw TException(e.getMessage());
	}
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::loadSoundTrack(const TFilePath &fileName)
{
	try {
		TSoundTrackP st;
		TFilePath path(fileName);
		bool ret = TSoundTrackReader::load(path, st);
		if (ret) {
			m_duration = st->getDuration();
			setName(fileName.getWideName());
			setSoundTrack(st);
		}
	} catch (TException &) {
		return;
	}
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::load()
{
	loadSoundTrack();
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::save()
{
	save(m_path);
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::save(const TFilePath &path)
{
	TSoundTrackWriter::save(path, m_soundTrack);
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::loadData(TIStream &is)
{
	is >> m_name;
	setName(m_name);

	std::string tagName;
	bool flag = false;

	int type = UNKNOWN_XSHLEVEL;

	for (;;) {
		if (is.matchTag(tagName)) {
			if (tagName == "path") {
				is >> m_path;
				is.matchEndTag();
			} else if (tagName == "type") {
				std::string v;
				is >> v;
				if (v == "sound")
					type = SND_XSHLEVEL;
				is.matchEndTag();
			} else
				throw TException("unexpected tag " + tagName);
		} else
			break;
	}
	setType(type);
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::saveData(TOStream &os)
{
	os << m_name;

	std::map<std::string, std::string> attr;
	os.child("type") << L"sound";
	os.child("path") << m_path;
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::computeValues(int frameHeight)
{
	if (frameHeight == 0)
		frameHeight = 1;
	m_values.clear();
	if (!m_soundTrack) {
		m_frameSoundCount = 0;
		m_samplePerFrame = 0;
		return;
	}

	m_samplePerFrame = m_soundTrack->getSampleRate() / m_fps;
	double samplePerPixel = m_samplePerFrame / frameHeight;

	int sampleCount = m_soundTrack->getSampleCount();
	if (sampleCount <= 0) // This was if(!sampleCount)  :(
		return;			  //

	m_frameSoundCount = tceil(sampleCount / m_samplePerFrame);

	double maxPressure = 0.0;
	double minPressure = 0.0;

	m_soundTrack->getMinMaxPressure(
		TINT32(0), (TINT32)sampleCount, TSound::LEFT, minPressure, maxPressure);

	double absMaxPressure = tmax(fabs(minPressure), fabs(maxPressure));

	if (absMaxPressure <= 0)
		return;

	// Adjusting using a fixed scaleFactor
	double weightA = 20.0 / absMaxPressure;

	long i = 0, j;
	long p = 0; //se p parte da zero notazione per pixel,
				//se parte da 1 notazione per frame
	while (i < m_frameSoundCount) {
		for (j = 0; j < frameHeight - 1; ++j) {
			double min = 0.0;
			double max = 0.0;
			m_soundTrack->getMinMaxPressure(
				(TINT32)(i * m_samplePerFrame + j * samplePerPixel),
				(TINT32)(i * m_samplePerFrame + (j + 1) * samplePerPixel - 1),
				TSound::MONO, min, max);
			m_values.insert(std::pair<int, std::pair<double, double>>(p + j, std::pair<double, double>(min * weightA, max * weightA)));
		}

		double min = 0.0;
		double max = 0.0;
		m_soundTrack->getMinMaxPressure(
			(TINT32)(i * m_samplePerFrame + j * samplePerPixel),
			(TINT32)((i + 1) * m_samplePerFrame - 1),
			TSound::MONO, min, max);
		m_values.insert(std::pair<int, std::pair<double, double>>(p + j, std::pair<double, double>(min * weightA, max * weightA)));

		++i;
		p += frameHeight;
	}
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::getValueAtPixel(int pixel, DoublePair &values) const
{
	std::map<int, DoublePair>::const_iterator it = m_values.find(pixel);
	if (it != m_values.end())
		values = it->second;
}

//-----------------------------------------------------------------------------

void TXshSoundLevel::setFrameRate(double fps)
{
	if (m_fps != fps) {
		m_fps = fps;
		computeValues();
	}
}

//-----------------------------------------------------------------------------

int TXshSoundLevel::getFrameCount() const
{
	int frameCount = m_duration * m_fps;
	return (frameCount == 0) ? 1 : frameCount;
}

//-----------------------------------------------------------------------------
//Implementato per utilita'
void TXshSoundLevel::getFids(std::vector<TFrameId> &fids) const
{
	int i;
	for (i = 0; i < getFrameCount(); i++)
		fids.push_back(TFrameId(i));
}