My app is music player and some of the mp3's have lower volume. I want to Boost audio volume more than 100% in react native.
I have to tried this plugin:
react-native-volume-control
react-native-system-setting
react-native-audio-manager
react-native-sound
No, It's not possible, You have to increase the volume of the file that is playing like for example the vlc player does when you increase the volume beyond 100%. It has nothing to do with the volume you set to the phone, it just compensates for files which have a more quiet audio track.
You can try Web Audio API
function amplifyMedia(mediaElem, multiplier) {
var context = new (window.AudioContext || window.webkitAudioContext),
result = {
context: context,
source: context.createMediaElementSource(mediaElem),
gain: context.createGain(),
media: mediaElem,
amplify: function(multiplier) { result.gain.gain.value = multiplier; },
getAmpLevel: function() { return result.gain.gain.value; }
};
result.source.connect(result.gain);
result.gain.connect(context.destination);
result.amplify(multiplier);
return result;
}
You may need to implement a Native Module yourself for js to call setStereoVolume() on your AudioTrack if you are using AudioTrack.Or if you are using ExoPlayer to play music,try implement a custom AudioProcessor to copy each channel and apply the amplification.
Related
I'm developing a Voip-Application and i have an edge case where i want to play two raw files at the same time.
When i have an incoming call from my application i am creating a new Mediaplayer and play a custom ringtone. When i get shortly after also an incoming GSM-call i create a new mediaplayer and play a knocking sound to give the user feedback that there is also a GSM-Call incoming. At the same time i want the custom ringtone to continue playing.
private fun setAudioAttributesForFile(audioUsage: Int): AudioAttributes {
return AudioAttributes.Builder()
.setUsage(audioUsage)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
}
private fun startRingtone(fileToPlay: Int): MediaPlayer {
return MediaPlayer().apply {
reset()
if (fileToPlay == R.raw.ring {
setAudioAttributes(setAudioAttributesForFile(AudioAttributes.USAGE_NOTIFICATION_RINGTONE))
} else {
setAudioAttributes(setAudioAttributesForFile(AudioAttributes.USAGE_MEDIA))
}
isLooping = true
Main.get().resources.openRawResourceFd(fileToPlay).use {
setDataSource(
it.fileDescriptor,
it.startOffset,
it.length
)
}
setOnPreparedListener { start() }
prepareAsync()
}
}
The problem that i have with this code is that as soon as the knocking sound is playing the ringtone gets muted by the system and as soon as the knocking sound is stopping the ringtone continues.
What i also tried:
Using only
AudioAttributes.USAGE_NOTIFICATION_RINGTONE. As soon as the knocking sound starts to play both mediaPlayers are getting muted.
If i leave the setAudioAttributes() call away and replace these four lines to
if (fileToPlay == R.raw.ring) {
setAudioAttributesForFile(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
} else {
setAudioAttributesForFile(AudioAttributes.USAGE_MEDIA)
}
then i can play those two files at the same time. The problem then is that the ringtone file is not shown as a ringtone instead it is only shown as a media file. So when i increase and decrease the volume of the ringtone the flag does not show that it is a ringtone.
Is there a way to play one sound as a Ringtone and another sound over it as a normal Media Sound?
Thanks in advance. Any help is appreciated.
Use sound pool if you want to play both sounds at the same time.
I'm using react-native-sound to playback looped audio files (exactly mp3 format). The problem is that there is a gap between the loops.
Here is my code example:
loadSound = (s) => {
let sound = new Sound(s, Sound.MAIN_BUNDLE, (error) => {
if (error) {
console.log('failed to load the sound', error);
return;
} else {
sound.setNumberOfLoops(-1);
}
});
return sound;
}
let sound = loadSound('campfire.mp3')
sound.play();
Is there any workaround how to make the loops to sound smooth?
Actually, this issue is open on github, but there is no solution yet...
There are gaps between loops because of the bug in Android MediaPlayer (which is used under the hood).
To fix the problem I've created the react-native-audio-exoplayer module, which has pretty same functionality as the react-native-sound, but it is based on the Android ExoPlayer. The API is a bit different but more robust and modern (have a look at the docs).
Later if I have time I'll do a pull request to introduce ExoPlayer in the react-native-sound.
But for now feel free to use react-native-audio-exoplayer as a good workaround (for now it's implemented only for Android).
Using the below version of the react-native-sounds fixed the gap issue.
https://github.com/Menardi/react-native-sound-gapless.git
From the README of the git repo:
Simply setting a track to loop on Android does not make it gapless,
instead leaving a short silence before restarting the track. However,
Android does actually support gapless playback between different
tracks. So, this fork essentially loads the same track twice, and gets
Android to handle the gapless playback for us. The downside is that
you will use more memory than before, because the track is loaded
twice. For most cases, this shouldn't matter, but you can profile your
app in Android Studio if you are concerned.
I have same issue with looping the sound. What I did to make it work is to call the same play sound function once sound play completed. I hope this will helps you.
function playBackground(){
bgSound = new Sound(bgMusic, (error, sound) => {
if (error) {
alert('error' + error.message);
return;
}
bgSound.play((success) => {
if(success)
{
// console.log("Play completed");
playBackground();
}
bgSound.release();
});
});
}
I am developing a karaoke app which consist of animation and playback song. The most important thing here is very precise synchronization between both.
I implemented it few months ago and on iOS 9/10 everything was working great. We had a problem with Android app (ExoPlayer) because there were too big delay between playback and animation. Finally we found out that the problem was caused by wrong song format (mp3) - which was explained here: https://github.com/google/ExoPlayer/issues/3233. We fixed it by packing song into mp4 format (on iOS there is still mp3 used).
I use AVPlayer with HLS
self.player = AVPlayer(url: url)
//
var currentTime_: Double {
if let player = self.player {
return player.currentTime().seconds
}
return 0
}
Everything was ok until iOS 11 release. On iOS 11 there is the same desynchronization (player.currentTime is not accurate) that was on Android.
What's interesting is that even app that was build on iOS 10 SDK and is available on AppStore doesn't work properly on iOS 11 - but it still works great on iOS 10.
Nothing on server side was changed. So Apple had to change something in decoding/buffering. Right now we are working on changing audio format/decoding but still I am curious - why that has happened? Anyone encountered something similar?
Regards
You need use this option when create AVURLAsset
let asset = AVURLAsset(url: url, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
If you not use this option, AVPlayer measures mp3 audio duration by file length, so it has small error to get duration.
As woosiki pointed it out, you need to use the AVURLAsset. Just keep in mind that loading of large files will take longer due to the pre-calculation of the precise duration. You may want to put a loader indicator.
func prepareAudioFile(with track: Track) {
guard let url = URL(string: track.streamURL) else {
return
}
let asset = AVURLAsset(url: url,
options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
observePlayerProgress()
}
private func observePlayerProgress() {
let interval = CMTimeMake(value: 1, timescale: 5)
player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
if let track = self?.player.currentItem, track.status == .readyToPlay {
// Once the loading is finished this callback will return
// Here you can calculate and set duration and elapsed time (track.duration, time.seconds)
}
}
}
My Mobile App provides access to a large database of mp3 Audios. The App also allows the user to start an Audio from a specific position (basically last played position).
Whenever I try to run an audio from a given position, it first run the audio from the start for a second and then jumps to the given position.
I have also tried muting the audio but apparently mute also doesn't work after the first instance.
Here is how I am try to do this:
LastAudioPosition = 25;
$(this).jPlayer("play",LastAudioPosition);
After not finding a solution anywhere I ultimately settled with almost perfect solution. The idea is to mute the player for a small duration while the wrong part is played and then unmute it:
$("#jquery_jplayer_1").jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3: gsLink
}).jPlayer("play",gQFA_LastAudioPosition);
},
ended: function() {
endFunction();
},
canplay: function() {
$(this).jPlayer("mute");
$(this).jPlayer("play");
$(this).jPlayer("pause");
$(this).jPlayer("play",gQFA_LastAudioPosition);
setTimeout(function () {
$("#jquery_jplayer_1").jPlayer("unmute");
}, 200);
},.................
// Standard HTML5 implementation of StartMusic.
function Html5StartMusic(music)
{
var player = document.getElementById('musicPlayer');
player.volume = 0.1;
player.setAttribute('src', 'music/' + music + '.ogg');
player.play();
}
Setting volume does work in PC Chrome, but not in Android 2.3 Webkit. Is there an alternative way to make it work?
Regards,
Finally, I've workarounded the problem, writing my own player at the application side, that supports volume control. To callback player functions I use onJsAlert() as API (onConsoleMessage() seems to be better, but I heard on some phones it's disabled).
Try:
yourAudioElement.mute = true