2017-01-11 52 views
-1

嗨,我想从董事会记录,我已成功记录4秒。问题是当我尝试记录更多时间时,我得到一个错误,告诉我没有足够的记忆。我的目标是记录一个5分钟的文件。到现在为止,我已经创建了一个名为snIn [256]的缓冲区,其中是样本。我把它发送到[16K * 4sec]的大缓冲区,当它已满时,我创建wav文件。如何填写wavfile的“数据字段”

#include "SAI_InOut.hpp" 
#include "F746_GUI.hpp" 
#include "Delay.hpp" 
#include "WaveformDisplay.hpp" 
#include "SDFileSystem.h" 
#include "wavfile.h" 
using namespace Mikami; 

#define RES_STR_SIZE 0x20 
#define WAVFILE_SAMPLES_PER_SECOND 16000 
#define REC_TIME 4 

    //Create an SDFileSystem object 
SDFileSystem sd("sd"); 

bool flag = 1; 
int count = 0; 
char *res_buf; 
int rp = 0; 
const int NUM_SAMPLES = WAVFILE_SAMPLES_PER_SECOND * REC_TIME; 
Array<int16_t> my_buffer(NUM_SAMPLES); 
int j = 0; 
static const char *target_filename = "/sd/rectest.wav";  
const int SEG_SIZE = 256; 
int sent_array = 0; 


int rec(const char *filename, Array<int16_t> my_buffer) 
{ 
    j = 0; 
    flag = 0; 
    sent_array = 0; 

    WavFileResult result; 
    wavfile_info_t info; 
    wavfile_data_t data; 

    WAVFILE_INFO_AUDIO_FORMAT(&info) = 1; 
    WAVFILE_INFO_NUM_CHANNELS(&info) = 1; 
    WAVFILE_INFO_SAMPLE_RATE(&info)  = WAVFILE_SAMPLES_PER_SECOND; 
    WAVFILE_INFO_BITS_PER_SAMPLE(&info) = 16; 
    WAVFILE_INFO_BYTE_RATE(&info)  = WAVFILE_INFO_NUM_CHANNELS(&info) * WAVFILE_INFO_SAMPLE_RATE(&info) * (WAVFILE_INFO_BITS_PER_SAMPLE(&info)/8); 
    WAVFILE_INFO_BLOCK_ALIGN(&info)  = 2; 


    WAVFILE *wf = wavfile_open(filename, WavFileModeWrite, &result); 
    if (result != WavFileResultOK) { 
     wavfile_result_string(result, res_buf, RES_STR_SIZE); 
     printf("%s", res_buf); 
     return result; 
    } else printf ("Open file success \r\n"); 

    rp = 0; 
    WAVFILE_DATA_NUM_CHANNELS(&data) = 1; 

     result = wavfile_write_info(wf, &info); 
     if (result != WavFileResultOK) { 
      wavfile_result_string(result, res_buf, RES_STR_SIZE); 
      printf("%s", res_buf); 
      return result; } else printf ("Write info success \r\n"); 

    while (rp < NUM_SAMPLES) { 
     WAVFILE_DATA_CHANNEL_DATA(&data, 0) = my_buffer[rp];  
     result = wavfile_write_data(wf, &data); 
     rp += 1; 
    } 

    if (result != WavFileResultOK) { 
     wavfile_result_string(result, res_buf, RES_STR_SIZE); 
     printf("%s", res_buf); 
     return result; } else printf ("Write Data file success \r\n"); 

    result = wavfile_close(wf); 
    if (result != WavFileResultOK) { 
     wavfile_result_string(result, res_buf , RES_STR_SIZE); 
     printf("%s", res_buf); 
     return result; } else printf ("Close file success \r\n"); 

    //UnMount the filesystem 
    sd.unmount(); 

    printf("Success rec !\r\n"); 
    return 0; 
} 


int main() 
{ 
    //Mount the filesystem 
     sd.mount(); 

    const float MAX_DELAY = 0.5f;  // 最大遅延,単位:秒 
    const int FS = I2S_AUDIOFREQ_16K; // 標本化周波数: 16 kHz 
    const uint32_t MAX_ARRAY_SIZE = (uint32_t)(MAX_DELAY*FS); 
    SaiIO mySai(SaiIO::BOTH, 256, FS, INPUT_DEVICE_DIGITAL_MICROPHONE_2); 
    Label myLabel(185, 10, "Delay System", Label::CENTER, Font16); 
    // ButtonGroup: "ON", "OFF" 
    const uint16_t BG_LEFT = 370; 
    const uint16_t BG_WIDTH = 100; 
    const uint16_t BG_HEIGHT = 45; 
    ButtonGroup onOff(BG_LEFT, 40, BG_WIDTH/2, BG_HEIGHT, 
         2, (string[]){"ON", "OFF"}, 0, 0, 2, 1); 
    const uint16_t SB_LEFT = BG_LEFT - 320; 
    const uint16_t SB_WIDTH = 270; 
    const uint16_t SB_Y0 = 240; 
    char str[20]; 
    sprintf(str, " %3.1f [s]", MAX_DELAY); 
    SeekBar barDelay(SB_LEFT, SB_Y0, SB_WIDTH, 
        0, MAX_ARRAY_SIZE, 0, "0", "", str); 
    NumericLabel<float> labelDelay(SB_LEFT+SB_WIDTH/2, SB_Y0-40, "DELEY: %4.2f", 0, Label::CENTER); 
    DelaySystem delaySystem(MAX_ARRAY_SIZE); 
    WaveformDisplay displayIn(*GuiBase::GetLcdPtr(), SB_LEFT+7, 70, 256, 9,LCD_COLOR_WHITE, LCD_COLOR_CYAN,GuiBase::ENUM_BACK); 
    Label inLabel(SB_LEFT-30, 65, "IN"); 
    WaveformDisplay displayOut(*GuiBase::GetLcdPtr(), SB_LEFT+7, 130, 256, 9,LCD_COLOR_WHITE, LCD_COLOR_CYAN,GuiBase::ENUM_BACK); 
    Label outLabel(SB_LEFT-30, 125, "OUT"); 

    int runStop = 1; 
    Array<int16_t> snIn(mySai.GetLength()); 
    Array<int16_t> snOut(mySai.GetLength()); 

    mySai.RecordIn(); 
    mySai.PlayOut(); 
    mySai.PauseOut(); 


    while (true) 
    { 
     // On/OFF 
     int num; 
     if (onOff.GetTouchedNumber(num)) 
      if (runStop != num) 
      { 
       if (num == 0) mySai.ResumeOut(); 
       else   mySai.PauseOut(); 
       runStop = num; 
      } 

     if (mySai.IsCompleted()) 
     { 
      for (int n=0; n<mySai.GetLength() ; n++) 
      { 
       int16_t xL, xR; 
       mySai.Input(xL,xR); 
       int16_t xn = xL + xR; 
       snIn[n] = xn; 
       my_buffer[j] = xn; 
       j++; 
       if (j == NUM_SAMPLES && flag == 1) { 
        rec (target_filename , my_buffer); } 

       int16_t yn = delaySystem.Execute(xn); 
       mySai.Output(yn, yn); 
       snOut[n] = yn; 
      } 

      mySai.Reset();  
      displayIn.Execute(snIn); 

     }  
    } 
} 

我连连想过一个可能的解决方案,以直接填写与SnIn系[256]缓冲液(而不是使用my_buffer)的wavefile的“数据区”,并在端部关闭wavfile。请让我知道你怎么想的是和其他解决方案

+2

所张贴的代码不编译和看起来更像C++比C推荐,至少,发布所包含的头文件,其中板,其中OS等 – user3629249

+0

这里的库的https://developer.mbed .org/users/shintamainjp/code/wavfile /#c853ba46d0b9 我正在使用stm32f746,mbed与keil ide – gab55

+0

嗯...也许尝试写较小的数据包(因为您可以处理4秒,也许尝试两秒包,所以你可以缓冲一个,而另一个写道)?我非常肯定,这在有限的记忆中运作良好;例如,我相信这是_Tales of Phantasia_通过不断从ROM中加载微小的片段到声音处理器的32 kB RAM来设法让SNES播放完全有声的开场曲。 (它也有一个自定义的声音驱动程序,虽然,设法有效地加倍声音RAM,但我离题...) –

回答

0

注意事项:1)当进行写操作,更多的数据仍然在未来

至少,我会仔细缓冲区数据,所以可以写一个缓冲区,而另一个填满。

通常这意味着使用的中断以收集样品(为当前正被提起过缓冲器。)

前台程序等待当前缓冲器为“满”,然后启动写操作。,

然后再次等待缓冲区为“满”

中断函数跟踪正在填充哪个缓冲区以及该缓冲区的当前索引。当缓冲区已满时,设置'全局'状态以让前台程序知道哪个缓冲区已准备好写入。

前台程序写入缓冲区,然后重置该缓冲区的状态。

+0

我明白你说什么,但这不是我现在的问题。我试图记录一个5分钟的文件,但我只有320k的RAM在板上,我需要绕过这一点。如何制作一个长的wav文件而不需要制作一个巨大的数组? – gab55

+0

你只有320K的内存。因此,44.1kHz的4秒音频将会占用更多的内存。你需要加倍缓冲区和大概1024个样本的处理,如果你正在做一些priocessing,可能会上升。 。 –