Here's my problem:
In my game, I want to have a mini game using a microphone, à la Zelda Phantom Hourglass or Wario Ware. So far, it's globally working. I think I manage to make it work.
But, there is one problem that I couldn't solve: when I try to change the recording channel(= the microphone in this case), I have a massive memory leak. I think it's because I can't delete the buffer.
I tried many things to have it deleted, but so far, to no avail. I even tried to delete the buffer before even using it but that doesn't work.
My guess is: since I cannot delete the buffer, when I try to change the microphone, the data stacks and records two voices at the time. The mini game in question asks you to be quiet for 1 minute, so if the microphone is recording twice, it makes twice too much "sound" and if you make too much sound, you fail the mini game.
Here is the code I'm trying to make work:
CREATE
global.RecordDevice = undefined;
if (global.RecordDevice = undefined)
{
count = audio_get_recorder_count();
switch(count)
{
case 0:
global.RecordDevice = 1000;
break;
case 1:
global.RecordDevice = 0;
break;
default:
global.RecordDevice = get_integer(string(count) + " audio device(s) detected? Which one should we use ? (type in a number between 0 to " + string(count - 1) + ")", 0);
break;
}
if (global.RecordDevice = NaN)
{
show_debug_message("error")
}
else if (global.RecordDevice < count)
{
var map = audio_get_recorder_info(global.RecordDevice);
var device = string(global.RecordDevice);
var name = map[? "name"];
var str_rate = " Sample rate: " + string(map[? "sample_rate"]);
info = device + name + ".\nIs it ok?";
draw_text(150,500,info);
ds_map_destroy(map);
drawing = true;
microphone_volume = 0;
us_old = -1;
msg = 0;
audio_queue = audio_create_play_queue(buffer_s16, 44100, audio_mono);
audio_record = audio_start_recording(global.RecordDevice);
graph = ds_list_create();
audio_buffer = buffer_create(44100, buffer_grow, 2);
pos = buffer_tell(audio_buffer);
}
else if (global.RecordDevice = undefined)
{
show_message("No sound detected. Something's up with your pc?")
instance_destroy();
}
else if (global.RecordDevice >= count)
{
show_message("Nope, that's too high. Error.")
instance_destroy();
}
}
timer= 0;
EVENT
if (global.RecordDevice = 1000)
{
show_message("No sound detected. Something's wrong with your pc?")
}
if (global.RecordDevice != 1000)
{
if (microphone_volume !=0)
{
}
}
if (keyboard_check_pressed(vk_f1))
{
audio_stop_recording(global.RecordDevice);
audio_free_play_queue(audio_queue);
buffer_delete(0);
audio_free_buffer_sound(0);
buffer_delete(audio_buffer);
audio_free_buffer_sound(audio_buffer);
global.RecordDevice = undefined;
room_restart();
}
Async Recording
var len = async_load[? "data_len"];
buffer_seek(audio_buffer,buffer_seek_start,0);
buffer_copy(async_load[? "buffer_id"], 0, len, audio_buffer, 0);
var alpha = 0.003;
for (var i = 0;i < len/16; i++)
{
var us = buffer_read(audio_buffer, buffer_s16);
if (us_old == -1) us_old = us;
us = alpha * us + (1.0 - alpha) * us_old;
us_old = us;
microphone_volume = us;
if (drawing)
{
ds_list_insert(graph,0,microphone_volume);
}
}
if (microphone_volume=0)
{
timer++;
if (timer>60)
{
show_message("No sound detected. Something's wrong with your pc?")
}
}
Async Audio reading
var q_id = async_load[? "queue_id"];
if (q_id == audio_queue)
{
audio_free_play_queue(audio_queue);
buffer_delete(audio_buffer);
}
GUI (this works fine)
var s = info;
msg = ("Ok. Donc on utilise le périphérique appelé\n" + s );
if (drawing)
{
for (var i = 0; i < ds_list_size(graph);i++)
{
if (i/20 <= window_get_width())
{
draw_point(i/20,300-(ds_list_find_value(graph,i)/32));
}
else
{
ds_list_delete(graph,i);
}
}
draw_set_color(c_white);
draw_set_halign(fa_left);
draw_text(150,80, "Current micro's volume");
draw_text(150,380, "Press F1 to change your mind");
draw_rectangle_color(100,200, string(microphone_volume), 250, c_green,c_green,c_green,c_green,0);
}
When I run this code, this is the log I have everytime I change the microphone
audio_stop_recording : recorder 1 is not currently recording
create queue 200000
audio_start_recording: device 1 already recording
Thank you very much for your help. I know this is very specific but since there is little to no clear documentation about it - and even less people who actually try to use a microphone in their game - I kind of came to a dead end with this problem...
I tried to figure out the problem by myself by changing and tweaking some parts of the code. I read, read and read again the documentation provided by GameMaker (but to be honest, this part of the documentation is sometimes very vague). I tried to search the problem on google, to see if some people had the same problem. Spoiler: yes, some had the problem. There are two cases: those who never found the solution, and those who found it but didn't really explain how they did. I also tried to reach Game Maker devs, but... I was kind of being ignored so...
The only clue I found that might be useful is that when you start an async recording, GameMaker automatically creates a buffer of its own. So it might have something to do with a conflict between buffers. But if I don't create my own buffer, nothing works. And I really don't know how to delete the automatic buffer.