2013-05-01 27 views
5

Điều gì sẽ là thực hành tốt nhất để bỏ một mảng void vào typedef?Cast void to typedef (thực hành tốt nhất)

Đây là cách tôi hiện đang làm việc đó:

typedef struct { 
    int16_t left,right; 
} SampleStereo16; 

void *buffer[100000]; // data buffer 
SampleStereo16* sample; 

// insert something here that writes to the buffer 

sample = (SampleStereo16*) buffer; 

Điều này dường như làm việc tốt nhưng không hiểu sao tôi có cảm giác có một cách tốt hơn. Tôi cũng tự hỏi nếu có cách nào để có mảng mẫu và bộ đệm chia sẻ cùng một bộ nhớ (bây giờ họ từng sử dụng bộ nhớ riêng của họ).

Đây là mã đầy đủ Tôi hiện đang làm việc trên:

#include "fmod.h" 
#include "fmod.hpp" 
#include "fmod_errors.h" 
#include "wincompat.h" 
#include <stdio.h> 

typedef struct { 
    int16_t left,right; 
} SampleStereo16; 

void ERRCHECK(FMOD_RESULT result) 
{ 
    if (result != FMOD_OK) 
    { 
     printf("\nFMOD error! (%d) %s\n", result, FMOD_ErrorString(result)); 
     if (result != FMOD_ERR_FILE_EOF) 
      exit(-1); 
    } 
} 


int main(int argc, char *argv[]) 
{ 
    FMOD::System  *system; 
    FMOD::Sound  *sound; 
    FMOD_RESULT  result; 
    unsigned int  version; 

    int channels; 
    int bits; 

    unsigned int   lenbytes; // length in bytes read 
    void     *buffer[1000000]; // data buffer 
    unsigned int   *read; // number of bytes actually read 
    unsigned int  position; // offset in PCM samples 
    unsigned int   samplesread; // number of PCM samples read 
    unsigned int  samplesbuffer; // 
    unsigned int  cueposition; 

    SampleStereo16*  sample; 


    /* 
     Create a System object and initialize. 
    */ 

    result = FMOD::System_Create(&system); 
    ERRCHECK(result); 

    system->getVersion(&version); 

    result = system->getVersion(&version); 
    ERRCHECK(result); 

    if (version < FMOD_VERSION) 
    { 
     printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION); 
     getch(); 
     return 0; 
    } 

    result = system->setOutput(FMOD_OUTPUTTYPE_ALSA); 
    ERRCHECK(result); 

    result = system->init(32, FMOD_INIT_NORMAL, 0); 
    ERRCHECK(result); 

    result = system->createStream("/home/dpk/Dropbox/Music/Will Smith - Miami.mp3", FMOD_SOFTWARE, 0, &sound); 


    result = sound->getFormat(0, 0, &channels, &bits); 
    ERRCHECK(result); 

    printf("channels : %d bits : %d \n", channels, bits); 

    if (channels!=2 and bits!=16) 
    { 
     printf("File must be stereo (2 channels) 16 bits \n"); 
     exit(-1); 
    } 

    lenbytes = sizeof(buffer); 
    samplesbuffer = lenbytes/channels/(bits/8); 
    position = 0; 
    cueposition = 0; 

    do 
    { 
     result = sound->seekData(position); 
     ERRCHECK(result); 

     printf("Reading block : %u ",position); 

     result = sound->readData(&buffer, lenbytes, read); 
     ERRCHECK(result); 

     samplesread = *read/channels/(bits/8); 

     sample = (SampleStereo16*) buffer; 

     printf("number of PCM samples read : %u \n", samplesread); 


     for(unsigned int i=0; i<samplesread; i++) 
     { 
      if (cueposition==0 && (abs(sample[i].left)>500 || abs(sample[i].right)>500)) 
      { 
       cueposition = position+i; 
       printf("cue point : %u \n", cueposition); 
      } 
     } 

     position += lenbytes/channels/(bits/8); 

    } while(samplesread==samplesbuffer); 

    printf("\nExit\n"); 

    /* 
     Shut down 
    */ 
    result = sound->release(); 
    ERRCHECK(result); 
    result = system->close(); 
    ERRCHECK(result); 
    result = system->release(); 
    ERRCHECK(result); 

    return 0; 
} 

Tôi cũng nhận lỗi segmentation khi tăng bộ đệm quá nhiều, nhưng từ những gì tôi đã có thể tìm thấy cho đến nay nó có vẻ là giới hạn kích thước ngăn xếp.

Cũng cảm thấy tự do để bình luận về bất cứ điều gì tôi đang làm sai, tôi chỉ mới gần đây (tuần trước) bắt đầu C++ vì vậy tôi khá chắc chắn một số điều trông xấu trong mã của tôi.

+3

Nếu bạn mới bắt đầu C++ tuần trước, đây không phải là cách để học C++ và chương trình C++ vào năm 2013. Bạn sẽ học được rất nhiều thói quen xấu mà bạn sẽ phải bỏ học. Nếu bạn muốn thử lập trình âm thanh, tôi sẽ xem xét SFML tại http://www.sfml-dev.org/tutorials/2.0/ Nó có giao diện trông giống như giao diện C++. –

+1

Bạn không thể có "một mảng trống". Những gì bạn có là một mảng của void * con trỏ *, mà gần như chắc chắn không phải là những gì bạn muốn * hoặc * có nghĩa là có *. Và "typedef" không phải là một loại C. Đó là một từ khóa được sử dụng để tạo bí danh cho một loại để bạn có thể tham khảo nó bằng tên khác với tên ban đầu của nó. Những gì bạn muốn cast là một * struct *, không phải là typedef. :) – jalf

+0

Đọc 'int không đọc 'của bạn;' không được cấp phát và có lẽ đó là lý do tại sao bạn có lỗi seg.Sử dụng một cái gì đó như thế này thay vì 'unsigned int read; result = sound-> readData (& buffer, lenbytes, &read); samplesread = read/channels/(bits/8); 'Tại sao thay vì void buffer bạn không sử dụng' SampleStereo16 buffer [10000]; sound-> readData (& buffer, 10000 * sizeof (SampleStereo16), &read); 'Điều này sẽ hoạt động. – Zuljin

Trả lời

5

buffer là một mảng con trỏ đến void. Điều đó thật bất thường. Thông thường chúng ta khai báo một bộ đệm như một mảng của char hoặc unsigned char hoặc uint8_t hay một số loại byte kích thước khác:

char buffer[100000]; // data buffer 

Dù sao, “đúng” C++ - phong cách dàn diễn viên là reinterpret_cast:

sample = reinterpret_cast<SampleStereo16 *>(buffer); 

On Mặt khác, bạn chỉ có thể khai báo buffer như một mảng của SampleStereo16 ở nơi đầu tiên. Sau đó, bạn không cần một diễn viên nào cả:

SampleStereo16 buffer[6250]; 
SampleStereo16 *sample; 

sample = buffer; 
+0

Vì vậy, trong thực tế những gì tôi đã làm là thiết lập dữ liệu của tôi như là địa chỉ vào những con trỏ? Trong thực tế những gì tôi đã làm là không chỉ bất thường nhưng một mô tả tốt hơn cho những gì tôi đã làm sẽ là "ngu ngốc". –

+0

Không đảm bảo rằng một mảng 'char' được căn chỉnh đúng cho loại' SampleStereo16'. Tạo một mảng 'SampleStereo16' gọn gàng giải quyết vấn đề đó. –

+0

@Keith: Tôi biết điều đó, nhưng đối với phần đó tôi đã dựa vào thực tế là bộ đệm của tôi là một bội số của SampleStereo16 và chức năng FMOD được sử dụng chỉ trả về toàn bộ các mẫu PCM nếu không âm thanh phải bị hỏng trong địa điểm đầu tiên. Điều đầu tiên tôi đã thử là khai báo một mảng của SampleStereo16 nhưng tôi đã làm 'SampleStereo16 * buffer [6250];' và điều đó đã cho tôi một lỗi nói rằng nó đã bị vô hiệu, nhưng bây giờ tôi hiểu những gì tôi đã làm sai. Khái niệm về con trỏ có thể khá khó hiểu khi bạn mới dùng C++. –

0

Bạn nên sử dụng toán tử sizeof để tìm ra số lượng mẫu đã được đọc. Tức là, mảng byte của bạn phải là bội số của kích thước (SampleStereo16).

Sau đó, bạn thường sẽ đi bộ mảng byte theo các khối có kích thước đó. Bạn malloc (sizeof (SampleStereo16)) để có được mỗi con trỏ SampleStereo16 *, sau đó memcpy số lượng dữ liệu đó từ mảng byte của bạn và thêm nó vào vectơ hoặc mảng của bạn.

Nếu bạn đóng gói và giải nén từng mảng cấu trúc của bạn một cách nhất quán theo cách đó, bạn sẽ không gặp vấn đề gì. Nó cũng rất phổ biến để phân bổ một vài byte đầu tiên trong tệp tuần tự của bạn đến một số phiên bản của một số loại, trong trường hợp bạn quyết định thêm nhiều trường vào cấu trúc của bạn sau này, nhưng nó có vẻ không phải là trường hợp sử dụng của bạn ở đây, dựa trên toàn bộ mẫu mã của bạn.