I am developing an iOS app which allows users to practice shadowing (*language learning method). Thus, I’d like to play audios and record your voice simultaneously. However, during recording, playing audio is very unstable e.g. low volume, unnatural pitch, etc. Is there any way to do it?
My cord is as below. It would be grateful if you give me any insight.
const loadNewPlaybackInstance = async (audioPath, playbackInstance, setState) => {
if (playbackInstance !== null) {
await playbackInstance.unloadAsync()
playbackInstance = null
}
const initialStatus = {
shouldPlay: false,
rate: 1,
shouldCorrectPitch: true,
volume: 1,
isMuted: false,
isLooping: false,
}
const { sound, status } = await Audio.Sound.createAsync(audioPath, initialStatus)
setState(sound)
}
const beginRecording = async () => {
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_MIX_WITH_OTHERS,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DUCK_OTHERS,
playThroughEarpieceAndroid: true,
staysActiveInBackground: false,
})
const recording = new Audio.Recording()
const recordingSettings = JSON.parse(JSON.stringify(Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY))
await recording.prepareToRecordAsync(recordingSettings)
recordingInstanceRef.current = recording
await recordingInstanceRef.current.startAsync()
}
useEffect(() => {
const { audioPath } = script[sourceId].sourceContents[unitId]
loadNewPlaybackInstance(audioPath, playbackInstance, updatePlaybackInstance)
}, [])
useEffect(() => {
if (!onPlayingAudio && playbackInstance) {
playbackInstance.stopAsync()
}
}, [onPlayingAudio])
useEffect(() => {
if (currentSentenceId) {
const currentIndex = getCurrentIndex(sourceId, unitId, currentSentenceId)
const positionMillis = 1000*script[sourceId].sourceContents[unitId].sentences[currentIndex].position
playbackInstance.playAsync()
playbackInstance.setPositionAsync(positionMillis)
}
}, [currentSentenceId])
useEffect(() => {
if (onRecording) {
beginRecording()
} else if (recordingInstanceRef.current){
stopRecording()
}
}, [onRecording])