I am using Codea sound(soundBuffer(PCM data)) to play my music data.Is there anyway to stop the sound when it playing?
(I I have my music data divided into several small off, but it sounds bad?
my sound player works(it can pause and stop when playing a sound), but there are "Sonic Boom
" (the bad sound). I test two of my music tracks , one is perfect and another has “Sonic Boom”.
I think I should remix the bad one.
Hi @Fred, my code of the sound player and the PCM data of the test the link below
https://gist.github.com/3815951
https://gist.github.com/3815924
Sound format : smaple rate = 22050 16bits per sample mono
Sorry, forget to remove the test buttons from CcSound.lua , the last code
musicList = {
"MUSIC_CallSome00",
"MUSIC_DiDiDo00",
"MUSIC_DiDiDo01",
"MUSIC_Flute00",
"MUSIC_G_Song00",
"MUSIC_HardGt08",
"MUSIC_LongDu03",
"MUSIC_LoopAccGT00",
"MUSIC_LoopAccGT01",
"MUSIC_LoopAccGT05",
"MUSIC_LoopSoundCrastal_Menu"
}
CcSound = class()
function CcSound:init()
self.volume = .5
watch("Volume")
Volume = self.volume
self.pickedSound = nil
self.music = {
MUSIC_CallSome00=MUSIC_CallSome00,
MUSIC_DiDiDo00=MUSIC_DiDiDo00,
MUSIC_DiDiDo01=MUSIC_DiDiDo01,
MUSIC_Flute00=MUSIC_Flute00,
MUSIC_G_Song00=MUSIC_CallSome00,
MUSIC_HardGt08=MUSIC_HardGt08,
MUSIC_LongDu03=MUSIC_LongDu03,
MUSIC_LoopAccGT00=MUSIC_LoopAccGT00,
MUSIC_LoopAccGT01=MUSIC_LoopAccGT01,
MUSIC_LoopAccGT05=MUSIC_LoopAccGT05,
MUSIC_LoopSoundCrastal_Menu=MUSIC_LoopSoundCrastal_Menu
}
self.lastTime = ElapsedTime
local bw, bh = WIDTH*.1, HEIGHT*.1
local posY, posX = HEIGHT*.2, (WIDTH - bw)*.5
self.UI = { Play = CcButton( "Play", vec2(posX-bw*1.5, posY), bw, bh
, function() self:Play() end, nil
, "Planet Cute:Water Block", bh*.3 )
, Pause = CcButton( "Pause", vec2(posX, posY), bw, bh
, function() self:Pause() end, nil
, "Planet Cute:Water Block", bh*.3)
, Stop = CcButton( "Stop", vec2(posX+bw*1.5, posY), bw, bh
, function() self:Stop() end, nil
, "Planet Cute:Water Block", bh*.3 )
, VolumeIn = CcButton( "Volume+", vec2(posX+bw, posY-bh*1.5), bw, bh
, function(e) self:TuneVolume(e) end, {volume=.1}
, "Planet Cute:Water Block", bh*.3 )
, VolumeOut = CcButton( "Volume-", vec2(posX-bw, posY-bh*1.5), bw, bh
, function(e) self:TuneVolume(e) end, {volume=-.1}
, "Planet Cute:Water Block", bh*.3 )
, pickedName = CcButton( "Picked Music : nil"
, vec2(WIDTH*.5-bw*4, posY+bh), bw*8, bh*.5, nil, nil
, "Cargo Bot:Register Slot", bh*.2 )
}
for i=1, #musicList do --music list
self.UI[musicList[i]] = CcButton( musicList[i], vec2(WIDTH*.5-bw*2, posY+bh*(2+i*.5-.5))
, bw*4, bh*.5
, function(e) self:PickMusic(e) end
, {name = musicList[i]}
, "Planet Cute:Selector", bh*.2 )
end
end
function CcSound:Update()
self.deltaTime = ElapsedTime - self.lastTime
self.lastTime = ElapsedTime
if self.pickedName then
self:UpdateSound(self.music[self.pickedName])
end
end
function CcSound:Draw()
for k, btn in pairs(self.UI) do
btn:Draw(color(255,255,255))
end
end
function CcSound:UpdateTouch(touch)
for k, btn in pairs(self.UI) do
btn:UpdateTouch(touch)
end
end
function CcSound:UpdateSound(musicData)
musicData.elapsedTime = musicData.elapsedTime + self.deltaTime
local flag = math.ceil( musicData.elapsedTime % musicData.length/musicData.setRate)
if musicData.flag ~= flag then
--print("flag",flag)
musicData.flag = flag
sound( soundbuffer(musicData[flag], musicData.format, musicData.sampleRate)
, self.volume
)
end
end
------ UI events
function CcSound:PickMusic(e)
self.pickedName = e.name
self.UI.pickedName.caption = "Picked Music : "..e.name
.."\
Length : "..self.music[e.name].length.."s"
end
function CcSound:Play()
if not self.pickedName then
self.pickedName = self.pendingName
self.pendingName = nil
end
end
function CcSound:TuneVolume(e)
self.volume = math.min(1, math.max(0, self.volume + e.volume))
Volume = self.volume
end
function CcSound:Pause()
self.pendingName = self.pickedName
self.pickedName = nil
end
function CcSound:Stop()
self.UI.pickedName.caption = "Please pick a music wav "
for k, musicData in pairs(self.music) do --reset poiter
musicData.elapsedTime = 0
end
self.pickedName = nil
end
Hi @ccYen, sorry it took a while for me to listen to your code - I kept crashing safari because the data was too big. So I downloaded it from gisthub and copied it to the iPad with iExplorer.
This is a clever approach, especially the pause feature. You have broken up your samples in one-second chunks, and you are playing them in order, unless the pause button is used. I’m surprised it works so smoothly!
When you say ‘sonic boom’ did you mean a click when the sample stops suddenly? Which one?This only happened to me a few times, but looking at your data, there are lots of one-second samples that do not end smoothly on /127. /127 is the middle value that represents 0, the part of the sound wave that means the diaphragm of your loudspeaker is at rest. If you end or start a sample too far plus or minus from the middle, you get a harsh click sound.
If this is indeed the problem, you could try to smooth out the end of the sample by playing data that takes you from the last value gently to /127.
I haven’t made anything this good with soundbuffer, or solved the click problem myself before so I’m sorry I don’t have any code for you, just this idea.
Hi @Fred, thanks for the suggestion.Yes,there are lots of one-second samples that do not end smoothly on /127 at my data(MUSIC_LoopSoundCrastal_Menu.lua ).I get a harsh click sound.
I will try to smooth out the end of the data and tell you the result.