diff options
Diffstat (limited to 'src/aomusicplayer.cpp')
| -rw-r--r-- | src/aomusicplayer.cpp | 240 |
1 files changed, 179 insertions, 61 deletions
diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp index 3ba9cf1d..249e01e5 100644 --- a/src/aomusicplayer.cpp +++ b/src/aomusicplayer.cpp @@ -1,107 +1,225 @@ #include "aomusicplayer.h" -#if defined(BASSAUDIO) + AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app) - : QObject() { m_parent = parent; ao_app = p_ao_app; } -AOMusicPlayer::~AOMusicPlayer() { kill_loop(); } +#ifdef BASSAUDIO -void AOMusicPlayer::play(QString p_song) +AOMusicPlayer::~AOMusicPlayer() { - BASS_ChannelStop(m_stream); - - f_path = ao_app->get_music_path(p_song); - - if (p_song.startsWith("http")) { - m_stream = BASS_StreamCreateURL(f_path.toStdWString().c_str(), 0, - BASS_STREAM_AUTOFREE | BASS_UNICODE | - BASS_ASYNCFILE, NULL, NULL); - } else { - m_stream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, - BASS_STREAM_AUTOFREE | BASS_UNICODE | - BASS_ASYNCFILE); + for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { + BASS_ChannelStop(m_stream_list[n_stream]); } +} + +void AOMusicPlayer::play(QString p_song, int channel, bool loop, + int effect_flags) +{ + channel = channel % m_channelmax; + if (channel < 0) // wtf? + return; + QString f_path = ao_app->get_music_path(p_song); - this->set_volume(m_volume); + unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE | + BASS_UNICODE | BASS_ASYNCFILE; + if (loop) + flags |= BASS_SAMPLE_LOOP; + + DWORD newstream; + if (f_path.endsWith(".opus")) + newstream = BASS_OPUS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags); + else + newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags); if (ao_app->get_audio_output_device() != "default") - BASS_ChannelSetDevice(m_stream, BASS_GetDevice()); - if (enable_looping) { - BASS_ChannelFlags(m_stream, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP); + BASS_ChannelSetDevice(m_stream_list[channel], BASS_GetDevice()); + + QString d_path = f_path + ".txt"; + + loop_start[channel] = 0; + loop_end[channel] = BASS_ChannelGetLength(newstream, BASS_POS_BYTE); + if (loop && file_exists(d_path)) // Contains loop/etc. information file + { + QStringList lines = ao_app->read_file(d_path).split("\n"); + foreach (QString line, lines) { + QStringList args = line.split("="); + if (args.size() < 2) + continue; + QString arg = args[0].trimmed(); + + float sample_rate; + BASS_ChannelGetAttribute(newstream, BASS_ATTRIB_FREQ, &sample_rate); + + // Grab number of bytes for sample size + int sample_size = 16 / 8; + + // number of channels (stereo/mono) + int num_channels = 2; + + // Calculate the bytes for loop_start/loop_end to use with the sync proc + QWORD bytes = static_cast<QWORD>(args[1].trimmed().toFloat() * + sample_size * num_channels); + if (arg == "loop_start") + loop_start[channel] = bytes; + else if (arg == "loop_length") + loop_end[channel] = loop_start[channel] + bytes; + else if (arg == "loop_end") + loop_end[channel] = bytes; + } + qDebug() << "Found data file for song" << p_song << "length" + << BASS_ChannelGetLength(newstream, BASS_POS_BYTE) << "loop start" + << loop_start << "loop end" << loop_end; } - else { - BASS_ChannelFlags(m_stream, 0, BASS_SAMPLE_LOOP); + + if (BASS_ChannelIsActive(m_stream_list[channel]) == BASS_ACTIVE_PLAYING) { + DWORD oldstream = m_stream_list[channel]; + + if (effect_flags & SYNC_POS) { + BASS_ChannelLock(oldstream, true); + // Sync it with the new sample + BASS_ChannelSetPosition(newstream, + BASS_ChannelGetPosition(oldstream, BASS_POS_BYTE), + BASS_POS_BYTE); + BASS_ChannelLock(oldstream, false); + } + + if (effect_flags & FADE_OUT) { + // Fade out the other sample and stop it (due to -1) + BASS_ChannelSlideAttribute(oldstream, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, + -1, 4000); + } + else + BASS_ChannelStop( + oldstream); // Stop the sample since we don't need it anymore } - BASS_ChannelPlay(m_stream, false); + else + BASS_ChannelStop(m_stream_list[channel]); + + m_stream_list[channel] = newstream; + BASS_ChannelPlay(m_stream_list[channel], false); + if (effect_flags & FADE_IN) { + // Fade in our sample + BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0); + BASS_ChannelSlideAttribute(newstream, BASS_ATTRIB_VOL, + static_cast<float>(m_volume[channel] / 100.0f), + 1000); + } + else + this->set_volume(m_volume[channel], channel); + + this->set_looping(loop, channel); // Have to do this here due to any + // crossfading-related changes, etc. } -void AOMusicPlayer::set_volume(int p_value) +void AOMusicPlayer::stop(int channel) { - m_volume = p_value; - float volume = m_volume / 100.0f; - BASS_ChannelSetAttribute(m_stream, BASS_ATTRIB_VOL, volume); + BASS_ChannelStop(m_stream_list[channel]); } -QString AOMusicPlayer::get_path() { return f_path; } +void AOMusicPlayer::set_volume(int p_value, int channel) +{ + m_volume[channel] = p_value; + float volume = m_volume[channel] / 100.0f; + if (channel < 0) { + for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { + BASS_ChannelSetAttribute(m_stream_list[n_stream], BASS_ATTRIB_VOL, + volume); + } + } + else { + BASS_ChannelSetAttribute(m_stream_list[channel], BASS_ATTRIB_VOL, volume); + } +} -void AOMusicPlayer::kill_loop() { BASS_ChannelStop(m_stream); } +void CALLBACK loopProc(HSYNC handle, DWORD channel, DWORD data, void *user) +{ + QWORD loop_start = *(static_cast<unsigned *>(user)); + BASS_ChannelLock(channel, true); + BASS_ChannelSetPosition(channel, loop_start, BASS_POS_BYTE); + BASS_ChannelLock(channel, false); +} -#elif defined(QTAUDIO) -AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app) - : QObject() +void AOMusicPlayer::set_looping(bool toggle, int channel) { - m_parent = parent; - ao_app = p_ao_app; + qDebug() << "Setting looping for channel" << channel << "to" << toggle; + m_looping = toggle; + if (!m_looping) { + if (BASS_ChannelFlags(m_stream_list[channel], 0, 0) & BASS_SAMPLE_LOOP) + BASS_ChannelFlags(m_stream_list[channel], 0, + BASS_SAMPLE_LOOP); // remove the LOOP flag + BASS_ChannelRemoveSync(m_stream_list[channel], loop_sync[channel]); + loop_sync[channel] = 0; + } + else { + BASS_ChannelFlags(m_stream_list[channel], BASS_SAMPLE_LOOP, + BASS_SAMPLE_LOOP); // set the LOOP flag + if (loop_sync[channel] != 0) { + BASS_ChannelRemoveSync(m_stream_list[channel], + loop_sync[channel]); // remove the sync + loop_sync[channel] = 0; + } + if (loop_start[channel] > 0) { + if (loop_end[channel] == 0) + loop_end[channel] = BASS_ChannelGetLength(m_stream_list[channel], BASS_POS_BYTE); + if (loop_end[channel] > 0) // Don't loop zero length songs even if we're asked to + loop_sync[channel] = BASS_ChannelSetSync( + m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, loop_end[channel], + loopProc, &loop_start[channel]); + } + } } +#elif defined(QTAUDIO) -AOMusicPlayer::~AOMusicPlayer() { m_player.stop(); } +AOMusicPlayer::~AOMusicPlayer() { + for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { + m_stream_list[n_stream].stop(); + } +} -void AOMusicPlayer::play(QString p_song) +void AOMusicPlayer::play(QString p_song, int channel, bool loop, + int effect_flags) { - m_player.stop(); - + channel = channel % m_channelmax; + if (channel < 0) // wtf? + return; QString f_path = ao_app->get_music_path(p_song); - m_player.setMedia(QUrl::fromLocalFile(f_path)); + m_stream_list[channel].stop(); - this->set_volume(100); + m_stream_list[channel].setMedia(QUrl::fromLocalFile(f_path)); - m_player.play(); + this->set_volume(m_volume[channel], channel); + + m_stream_list[channel].play(); } -void AOMusicPlayer::set_volume(int p_value) +void AOMusicPlayer::stop(int channel) { - m_volume = p_value; - - qreal linearVolume = QAudio::convertVolume(m_volume / qreal(100), - QAudio::LogarithmicVolumeScale, - QAudio::LinearVolumeScale); - - m_player.setVolume(linearVolume * 100); + m_stream_list[channel].stop(); } -QString AOMusicPlayer::get_path() { return f_path; } - -void AOMusicPlayer::kill_loop() { m_player.stop(); } -#else -AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app) - : QObject() +void AOMusicPlayer::set_volume(int p_value, int channel) { - m_parent = parent; - ao_app = p_ao_app; + m_volume[channel] = p_value; + m_stream_list[channel].setVolume(m_volume[channel]); } +#else + AOMusicPlayer::~AOMusicPlayer() {} -void AOMusicPlayer::play(QString p_song) {} +void AOMusicPlayer::play(QString p_song, int channel, bool loop, + int effect_flags) {} + +void AOMusicPlayer::stop(int channel) {} -void AOMusicPlayer::set_volume(int p_value) {} +void AOMusicPlayer::set_volume(int p_value, int channel) {} -QString AOMusicPlayer::get_path() { return f_path; } +void loopProc(int handle, int channel, int data, int *user) {} -void AOMusicPlayer::kill_loop() {} +void AOMusicPlayer::set_looping(bool toggle, int channel) {} #endif |
