Hello.
With the microphone recording thing you can get the sounddata using RecordingDevice:getData() and with that you can create a source using love.audio.newSource(). Now I'd like to know if is possible to store that sounddata into a file (.wav? .mp3?) so I can play anytime whatever the microphone have recorded.
Thanks!
[Solved] Is there any way to save sounddata to a file?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
[Solved] Is there any way to save sounddata to a file?
Last edited by Intas on Fri Jan 04, 2019 4:54 am, edited 1 time in total.
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Is there any way to save sounddata to a file?
Hi and welcome to the forums!
You can write out the contents sample-by-sample using love.filesystem stuff, but löve doesn't have a way, as far as i know, to encode it to a format it can load; you could write out a wav header and then the data using the correct format, which would be the simplest format to do, in my opinion.
You can write out the contents sample-by-sample using love.filesystem stuff, but löve doesn't have a way, as far as i know, to encode it to a format it can load; you could write out a wav header and then the data using the correct format, which would be the simplest format to do, in my opinion.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Is there any way to save sounddata to a file?
Hey zorg, thanks for replying!
Could you point me in the right direction on how could I do this? Is it something I should do using ffi? I'm completely unfamiliar with it
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Is there any way to save sounddata to a file?
Here's a site i found that's helpful, in that it shows how the (most used variation of the) format works: http://soundfile.sapp.org/doc/WaveFormat/
You don't need to use the FFI for this though, it can be implemented with just lua, tables, numbers and some string manipulation (to write out the correctly formatted numbers)
You can get the sampling rate, bit depth and channel count from the sounddata itself.
You don't need to use the FFI for this though, it can be implemented with just lua, tables, numbers and some string manipulation (to write out the correctly formatted numbers)
You can get the sampling rate, bit depth and channel count from the sounddata itself.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Is there any way to save sounddata to a file?
Okay, so I found this which seems to be what I want. It's made in pure lua so I have to change lua's IO with love.filesystem.
The only problem is that I don't know what "samples" should contain? According to the test file the samples are calculated like this: math.sin(i % 44100 / 44099 * freq) * 32767
Where:
Guess I'll have to actually understand the wave formatting and write my own "formatter"...
Code: Select all
require("wav")
-- ...
local samples = {}
local sounddata = rd:getData()
rd:stop()
local source = love.audio.newSource(sounddata)
love.audio.play(source) -- Play whatever was recorded
local w = wav.create_context("audiotest.wav", "w")
local channelCount = sounddata:getChannelCount()
local sampleRate = sounddata:getSampleRate()
local bitDepth = sounddata:getBitDepth() -- bits per sample
w.init(channelCount, sampleRate, bitDepth)
w.write_samples_interlaced(samples) -- ???
w.finish()
Where:
- i is a number from 0 to 44100*3
- 44100 is the sample rate,
- 44099 is sample rate - 1,
- freq is math.pi * 2 * 500
- 32767 is the maximum value for a signed integer?
Guess I'll have to actually understand the wave formatting and write my own "formatter"...
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Is there any way to save sounddata to a file?
The samples would be the audio data you want to write out, contained within the sounddata;
Since i'm guessing write_samples_interlaced wants a lua table of values, you need to fill a table with the samplepoints you can get from the sounddata with the :getSample method (indexed from 0 to sounddata:getSampleCount-1), then, since that method returns values in the range of [-1.0,1.0], you need to convert that to signed 16bit integers;
The multiplication by 32767 will work for that, although you should restrict it with math.min and math.max as well (limits are -32768 and 32767 inclusive), and you should also math.floor it at the end, to be sure.
That said, if the bit depth would be 8, it would be either signed or unsigned bytes instead, it's in the specs i linked... interlaced means the channels' samplepoints are woven together, e.g.: left1, right1, left2, right2, etc...; löve already uses this format internally if the sounddata has two channels, but it shouldn't work too differently if there's only 1 channel, since there's nothing to interleave in that case.
(And i understand what the intention of that test code is, looks like a simple sine wave generator, but i have zero idea about why it does the sampling rate division thing it does... Edit: I misread the precedence on that, it just wraps it, but the division, imo should still be with 44100 and not 44099; the frequency is 500 Hz, but they decided to include 2pi in that variable as well, probably for performance reasons; it's only needed because they're using a trigonometric function to generate the samplepoints (sine), making the cycle be [0,1] instead of [0,2*pi].)
Since i'm guessing write_samples_interlaced wants a lua table of values, you need to fill a table with the samplepoints you can get from the sounddata with the :getSample method (indexed from 0 to sounddata:getSampleCount-1), then, since that method returns values in the range of [-1.0,1.0], you need to convert that to signed 16bit integers;
The multiplication by 32767 will work for that, although you should restrict it with math.min and math.max as well (limits are -32768 and 32767 inclusive), and you should also math.floor it at the end, to be sure.
That said, if the bit depth would be 8, it would be either signed or unsigned bytes instead, it's in the specs i linked... interlaced means the channels' samplepoints are woven together, e.g.: left1, right1, left2, right2, etc...; löve already uses this format internally if the sounddata has two channels, but it shouldn't work too differently if there's only 1 channel, since there's nothing to interleave in that case.
(And i understand what the intention of that test code is, looks like a simple sine wave generator, but i have zero idea about why it does the sampling rate division thing it does... Edit: I misread the precedence on that, it just wraps it, but the division, imo should still be with 44100 and not 44099; the frequency is 500 Hz, but they decided to include 2pi in that variable as well, probably for performance reasons; it's only needed because they're using a trigonometric function to generate the samplepoints (sine), making the cycle be [0,1] instead of [0,2*pi].)
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Is there any way to save sounddata to a file?
Ohhhh, right, that makes sense. I knew that :getSample existed but I didn't know how to convert those numbers to 16bit integers.zorg wrote: ↑Wed Jan 02, 2019 6:23 amSince i'm guessing write_samples_interlaced wants a lua table of values, you need to fill a table with the samplepoints you can get from the sounddata with the :getSample method (indexed from 0 to sounddata:getSampleCount-1), then, since that method returns values in the range of [-1.0,1.0], you need to convert that to signed 16bit integers;
IT'S WORKING NOW! Thank you sooooooo much for your help zorg, you've been really helpful
So my code looks like this, if there's something to add/remove/modify let me know.
Code: Select all
require("wav")
-- ...
local sounddata = rd:getData()
rd:stop()
local channelCount = sounddata:getChannelCount()
local sampleRate = sounddata:getSampleRate()
local bitDepth = sounddata:getBitDepth()
local samples = {}
for i = 0, sounddata:getSampleCount() - 1 do
local sample = sounddata:getSample(i)
local n
local to16bit = sample * 32767
if (to16bit > 0) then
n = math.floor(math.min(to16bit, 32767))
else
n = math.floor(math.max(to16bit, -32768))
end
table.insert(samples, n)
end
local w = wav.create_context("test.wav", "w")
w.init(channelCount, sampleRate, bitDepth)
w.write_samples_interlaced(samples)
w.finish()
Again, thank you for your help (and patience all this audio stuff is new to me).
Re: [Solved] Is there any way to save sounddata to a file?
Cool! I was looking for an info about this too..thanks!
Who is online
Users browsing this forum: Ahrefs [Bot], Google [Bot] and 1 guest