示例#1
0
bool CPattern::SetSignature(const ROWINDEX rowsPerBeat, const ROWINDEX rowsPerMeasure)
//------------------------------------------------------------------------------------
{
	if(rowsPerBeat < GetSoundFile().GetModSpecifications().patternRowsMin
		|| rowsPerBeat > GetSoundFile().GetModSpecifications().patternRowsMax
		|| rowsPerMeasure < rowsPerBeat
		|| rowsPerMeasure > GetSoundFile().GetModSpecifications().patternRowsMax)
	{
		return false;
	}
	m_RowsPerBeat = rowsPerBeat;
	m_RowsPerMeasure = rowsPerMeasure;
	return true;
}
示例#2
0
void DeviceFrame::OnDeviceOpenSound(wxCommandEvent &) {
  wxString filename(GetSoundFile());
  if (filename.empty()) {
	return;
  }

  audiere::SampleSourcePtr source = audiere::OpenSampleSource(wxString2CStr(filename));
  if (!source) {
    wxMessageBox(
      wxT("Could not open source: ") + filename,
      wxT("Open Sound"), wxOK | wxCENTRE, this);
    return;
  }

  audiere::OutputStreamPtr stream = audiere::OpenSound(m_device, source);
  if (!stream) {
    wxMessageBox(
      wxT("Could not open sound: ") + filename,
      wxT("Open Sound"), wxOK | wxCENTRE, this);
    return;
  }

  // get the basename of the path for the window title
  wxString basename = wxFileNameFromPath(filename);
  new StreamFrame(this, wxT("Sound: ") + basename, stream.get(), source.get());
}
示例#3
0
// Add or remove rows from the pattern.
bool CPattern::Resize(const ROWINDEX newRowCount, bool enforceFormatLimits)
//-------------------------------------------------------------------------
{
	CSoundFile &sndFile = GetSoundFile();
	ModCommand *newPattern;

	if(enforceFormatLimits)
	{
		const CModSpecifications& specs = sndFile.GetModSpecifications();
		if(newRowCount > specs.patternRowsMax || newRowCount < specs.patternRowsMin) return false;
	} else
	{
		if(newRowCount > MAX_PATTERN_ROWS || newRowCount < 1) return false;
	}

	if(m_ModCommands == nullptr
		|| newRowCount == m_Rows
		|| (newPattern = AllocatePattern(newRowCount, GetNumChannels())) == nullptr)
	{
		return false;
	}

	// Copy over pattern data
	memcpy(newPattern, m_ModCommands, GetNumChannels() * std::min(m_Rows, newRowCount) * sizeof(ModCommand));

	FreePattern(m_ModCommands);
	m_ModCommands = newPattern;
	m_Rows = newRowCount;

	return true;
}
示例#4
0
bool CPattern::Expand()
//---------------------
{
	const ROWINDEX newRows = m_Rows * 2;
	const CHANNELINDEX nChns = GetNumChannels();
	ModCommand *newPattern;

	if(!m_ModCommands
		|| newRows > GetSoundFile().GetModSpecifications().patternRowsMax
		|| (newPattern = AllocatePattern(newRows, nChns)) == nullptr)
	{
		return false;
	}

	for(ROWINDEX y = 0; y < m_Rows; y++)
	{
		memcpy(newPattern + y * 2 * nChns, m_ModCommands + y * nChns, nChns * sizeof(ModCommand));
	}

	FreePattern(m_ModCommands);
	m_ModCommands = newPattern;
	m_Rows = newRows;

	return true;
}
示例#5
0
bool CPattern::Shrink()
//---------------------
{
	if (!m_ModCommands
		|| m_Rows < GetSoundFile().GetModSpecifications().patternRowsMin * 2)
	{
		return false;
	}

	m_Rows /= 2;
	const CHANNELINDEX nChns = GetNumChannels();

	for(ROWINDEX y = 0; y < m_Rows; y++)
	{
		const PatternRow srcRow = GetRow(y * 2);
		const PatternRow nextSrcRow = GetRow(y * 2 + 1);
		PatternRow destRow = GetRow(y);

		for(CHANNELINDEX x = 0; x < nChns; x++)
		{
			const ModCommand &src = srcRow[x];
			const ModCommand &srcNext = nextSrcRow[x];
			ModCommand &dest = destRow[x];
			dest = src;

			if(dest.note == NOTE_NONE && !dest.instr)
			{
				// Fill in data from next row if field is empty
				dest.note = srcNext.note;
				dest.instr = srcNext.instr;
				if(srcNext.volcmd != VOLCMD_NONE)
				{
					dest.volcmd = srcNext.volcmd;
					dest.vol = srcNext.vol;
				}
				if(dest.command == CMD_NONE)
				{
					dest.command = srcNext.command;
					dest.param = srcNext.param;
				}
			}
		}
	}

	return true;
}
示例#6
0
void DeviceFrame::DoOpenEffect(audiere::SoundEffectType type, wxString typestring) {
  wxString filename(GetSoundFile());
  if (filename.empty()) {
    return;
  }

  audiere::SoundEffectPtr effect = audiere::OpenSoundEffect(m_device, wxString2CStr(filename), type);
  if (effect) {
    wxString basename = wxFileNameFromPath(filename);
    wxString title;
    title.sprintf(wxT("Sound Effect (%s): %s"),
                  typestring.c_str(), basename.c_str());
    new SoundEffectFrame(this, title, effect);
  } else {
    wxMessageBox(
      wxT("Could not open sound effect: ") + filename,
      wxT("Open Sound Effect"), wxOK | wxCENTRE, this);
  }
}
示例#7
0
void DeviceFrame::OnDeviceOpenStream(wxCommandEvent &) {
  wxString filename(GetSoundFile());
  if (filename.empty()) {
    return;
  }

#if wxUSE_UNICODE
  wxCharBuffer buffFilename = filename.mb_str(wxConvUTF8);
  audiere::SampleSourcePtr source = audiere::OpenSampleSource(buffFilename.data());
#else
  audiere::SampleSourcePtr source = audiere::OpenSampleSource(filename);
#endif
  if (!source) {
    wxMessageBox(
      wxT("Could not open sample source: ") + filename,
      wxT("Open Stream"), wxOK | wxCENTRE, this);
    return;
  }

  audiere::LoopPointSourcePtr loop_source =
    audiere::CreateLoopPointSource(source);
  if (loop_source) {
    source = loop_source.get();
  }

  audiere::OutputStreamPtr stream = audiere::OpenSound(
    m_device,
    source,
    true);
  if (!stream) {
    wxMessageBox(
      wxT("Could not open output stream: ") + filename,
      wxT("Open Stream"), wxOK | wxCENTRE, this);
    return;
  }

  // get the basename of the path for the window title
  wxString basename = wxFileNameFromPath(filename);
  new StreamFrame(this, wxT("Stream: ") + basename, stream.get(), source.get(), loop_source.get());
}
示例#8
0
// Write some kind of effect data to the pattern. Exact data to be written and write behaviour can be found in the EffectWriter object.
bool CPattern::WriteEffect(EffectWriter &settings)
//------------------------------------------------
{
	// First, reject invalid parameters.
	if(!m_ModCommands
		|| settings.m_row >= GetNumRows()
		|| (settings.m_channel >= GetNumChannels() && settings.m_channel != CHANNELINDEX_INVALID))
	{
		return false;
	}

	CHANNELINDEX scanChnMin = settings.m_channel, scanChnMax = settings.m_channel;

	// Scan all channels
	if(settings.m_channel == CHANNELINDEX_INVALID)
	{
		scanChnMin = 0;
		scanChnMax = GetNumChannels() - 1;
	}

	ModCommand * const baseCommand = GetpModCommand(settings.m_row, scanChnMin);
	ModCommand *m;

	// Scan channel(s) for same effect type - if an effect of the same type is already present, exit.
	if(!settings.m_allowMultiple)
	{
		m = baseCommand;
		for(CHANNELINDEX i = scanChnMin; i <= scanChnMax; i++, m++)
		{
			if(!settings.m_isVolEffect && m->command == settings.m_command)
				return true;
			if(settings.m_isVolEffect && m->volcmd == settings.m_command)
				return true;
		}
	}

	// Easy case: check if there's some space left to put the effect somewhere
	m = baseCommand;
	for(CHANNELINDEX i = scanChnMin; i <= scanChnMax; i++, m++)
	{
		if(!settings.m_isVolEffect && m->command == CMD_NONE)
		{
			m->command = settings.m_command;
			m->param = settings.m_param;
			return true;
		}
		if(settings.m_isVolEffect && m->volcmd == VOLCMD_NONE)
		{
			m->volcmd = settings.m_command;
			m->vol = settings.m_param;
			return true;
		}
	}

	// Ok, apparently there's no space. If we haven't tried already, try to map it to the volume column or effect column instead.
	if(settings.m_retry)
	{
		const bool isS3M = (GetSoundFile().GetType() & MOD_TYPE_S3M);

		// Move some effects that also work in the volume column, so there's place for our new effect.
		if(!settings.m_isVolEffect)
		{
			m = baseCommand;
			for(CHANNELINDEX i = scanChnMin; i <= scanChnMax; i++, m++)
			{
				switch(m->command)
				{
				case CMD_VOLUME:
					m->volcmd = VOLCMD_VOLUME;
					m->vol = m->param;
					m->command = settings.m_command;
					m->param = settings.m_param;
					return true;

				case CMD_PANNING8:
					if(isS3M && settings.m_param > 0x80)
					{
						break;
					}

					m->volcmd = VOLCMD_PANNING;
					m->command = settings.m_command;

					if(isS3M)
					{
						m->vol = m->param >> 1;
					} else
					{
						m->vol = (m->param >> 2) + 1;
					}

					m->param = settings.m_param;
					return true;
				}
			}
		}
示例#9
0
CHANNELINDEX CPattern::GetNumChannels() const
//-------------------------------------------
{
	return GetSoundFile().GetNumChannels();
}