| |
| |
| #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) |
| 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 = std::max(fabs(minPressure), fabs(maxPressure)); |
| |
| if (absMaxPressure <= 0) return; |
| |
| |
| double weightA = 20.0 / absMaxPressure; |
| |
| long i = 0, j; |
| long p = 0; |
| |
| 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; |
| } |
| |
| |
| |
| void TXshSoundLevel::getFids(std::vector<TFrameId> &fids) const { |
| int i; |
| for (i = 0; i < getFrameCount(); i++) fids.push_back(TFrameId(i)); |
| } |
| |