Page 1 of 4 123 ... LastLast
Results 1 to 10 of 36

Thread: Byte-by-byte allocated data manipulation

  1. #1
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    Byte-by-byte allocated data manipulation

    I have a scenario where I am allocating a chunk of data for audio playback. The audio I'm loading from a MOD(XM/FastTracker2 to be specific) sample data. The trick however is that because the sample data is delta encoded for compression reasons, I now have to go byte-by-byte or word-by-word [size=9px](for 16-bit audio)[/size] through the whole thing and run it through a simple decryption algo.

    Here is the algo in semi-Pascal:
    [pascal]var
    old, new: ShortInt;

    old := 0;
    for i := 0 to data_len do
    begin
    new := sample[i] + old;
    sample[i] := new;
    old := new;
    end;[/pascal]

    Now how would I best access my audio data considering that I originally allocate and dump it like so...

    [pascal] {Sample Data}
    for j := NumberOfSamples - XmInstrument.NumOfSamples to NumberOfSamples - 1 do
    begin
    GetMem(Samples[j].SampleData, Samples[j].SampleLength);

    BlockRead(FileStream, Samples[j].SampleData^, Samples[j].SampleLength);
    end;[/pascal]

    I want to maintain my SampleData pointer as it is so that I can then later give this to whatever audio buffer loading function for OpenAL, DSound, etc... Beyond that I can use whatever additional structures I might need.


    EDIT: I guess my original question should have been how can I access a specific piece of the data after allocating it via GetMem().
    Jason McMillen
    Pascal Game Development
    Co-Founder





  2. #2

    Byte-by-byte allocated data manipulation

    I am not sure if I understand the question 100% but if I'm right you just want to access single bytes from a piece of memory.
    There are several good ways of which I show two here to get the idea.

    [pascal]var
    DataPtr: Pointer;
    BytePtr: ^Byte;
    DataSize: Integer;
    i: Integer;
    B: Byte;

    type
    TByteArray = array[0..100000000] of Byte;
    PByteArray = ^TByteArray;
    var
    BA: PByteArray;
    begin
    DataSize := 100;
    GetMem(DataPtr, DataSize);
    FillChar(DataPtr^, DataSize, 1);

    // method 1: typed pointer increment
    BytePtr := @DataPtr^;
    for i := 0 to DataSize - 1 do
    begin
    B := BytePtr^;
    Inc(BytePtr); // type pointer increment: address of BytePtr moves 1 byte
    end;

    // Method 2: array typecast
    BA := @DataPtr^;
    for i := 0 to DataSize - 1 do
    begin
    BytePtr := @BA^[i]; // make byteptr point to the right byte
    B := BA^[i]; // fill byte with value
    end;

    FreeMem(DataPtr);
    end;
    [/pascal]

  3. #3
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    Byte-by-byte allocated data manipulation

    Yup, you've basically got it.

    I also want to manipulate it then feed it back. I imagine I'd be able to assign it back to the Byte/Word pointer in the same manner?
    Jason McMillen
    Pascal Game Development
    Co-Founder





  4. #4
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    Byte-by-byte allocated data manipulation

    Actually the strangest thing is that I have to do also convert it from a signed value to an unsigned one. So I guess I'm looking at making all of these...

    [pascal]var
    AudioBuffer_8bit_Signed : ^ShortInt;
    AudioBuffer_16bit_Signed : ^SmallInt;
    AudioBuffer_8bit_Unsigned : ^Byte;
    AudioBuffer_16bit_Unsigned : ^Word;
    [/pascal]

    ...point the ones that I need (8 or 16 bit pairs) and then pass the data through them to convert it.

    That is to say with the issue of how the data will be altered aside. [size=9px](see my 'Sound' forum thread if anyone wants to help me with that one.)[/size]


    So anyhow I'd imagine that I'm on the right track?
    Jason McMillen
    Pascal Game Development
    Co-Founder





  5. #5

    Byte-by-byte allocated data manipulation

    I recommend to use dynamic arrays.
    Code:
    SetLength(Samples[j].SampleData, Samples[j].SampleLength); // Instead of GetMem
    if Samples[j].SampleLength > 0 then BlockRead(FileStream, Samples[j].SampleData[0], Samples[j].SampleLength * SizeOf(Samples[j].SampleData[0]));
    where Samples[j].SampleData is declared like this:
    Code:
    SampleData: array of Byte; // or whatever you want instead of byte
    Of course you can manipulate with the array data as you wish.

  6. #6

    Byte-by-byte allocated data manipulation

    If you are using Freepascal then you can use any pointer as array (C-Style).
    "someWordPtr[20] := 0" -> would access element #19.

    If not then you can only cast the pointer to an array or do the
    pointer-arithmetics by yourself: "inc(integer(workPtr), x*sizeof(someType))"

    Note that range checking doesn't work, of course.

  7. #7

    Byte-by-byte allocated data manipulation

    Quote Originally Posted by waran
    If you are using Freepascal then you can use any pointer as array (C-Style).
    "someWordPtr[20] := 0" -> would access element #19.
    SomeWordPtr[20] would access element no. 21.

  8. #8

    Byte-by-byte allocated data manipulation

    Quote Originally Posted by imcold
    Quote Originally Posted by waran
    If you are using Freepascal then you can use any pointer as array (C-Style).
    "someWordPtr[20] := 0" -> would access element #19.
    SomeWordPtr[20] would access element no. 21.
    That depends on what settings you have turned on in FPC.

    WILL, take a look at PChar's and PWord's. They are the fastest methods for direct memory addressing. Same as in C/C++ you can quickly inc and dec them as well as De-reference them for direct access. You can also do things such as (p+N)^ to access the Nth item (just remember that you will always be looking at N+1).

    Final note, PChar's and PWord's take less overhead then dynamic arrays but they do require that you alloc the block up front. Dynamic arrays take longer to access if your talking about Bytes or Words in comparison, but they do offer an easy way of resizing your structure if necessary.

  9. #9

    Byte-by-byte allocated data manipulation

    @imcold
    yeah, of course. Mixed it up - sry!

    @jdarling
    Delphis dynamic arrays aren't slower than any pointer since they
    use the very same technique. However they need a bit more space
    because they store also their lengths (you would do anyway when
    using a pointer, I guess).

  10. #10

    Byte-by-byte allocated data manipulation

    I agree with waran, the speed should be the same and I wouldn't wonder if the generated code would be the same, too. I'm not aware of any fpc switch that would make SomeWordPtr[20] point to something other than to elem. no. 21 (providing it's pointing at the beginning of some word array). Dynamic arrays need to be allocated before accessing just like pointers; the allocated memory can be resized with ReAllocMem easily.

Page 1 of 4 123 ... LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •