2017-01-11 48 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,可能會上升。 。 –