Solved

Convert bytes to flac_int32

Posted on 2007-11-15
22
434 Views
Last Modified: 2012-06-27
I'm trying to compress wave with FLAC codec but i don't know how to convert bytes to flac__int32. Here is the code i'm trying to make it work.

bool static FlacEncode(array<Byte>^ BytesToEncode,int nAudioBytesLeft)
                  {
                        unsigned char *cBuffer;
                        cBuffer =(unsigned char *)malloc(nAudioBytesLeft);
                        
                        for (int i =0; i < nAudioBytesLeft; ++i)
                              cBuffer[i]=BytesToEncode[i];
                  
                        while (nAudioBytesLeft > 0)
                        {
                              int nBytesToAdd = nAudioBytesLeft;

                              /* feed samples to encoder */
                              ok = FLAC__stream_encoder_process_interleaved(encoder, (FLAC__int32*)&cBuffer[0], nBytesToAdd);
                              nAudioBytesLeft -= nBytesToAdd;
                        }
                        return true;
                  }
0
Comment
Question by:so3
  • 10
  • 8
22 Comments
 
LVL 40

Expert Comment

by:evilrix
ID: 20292710
What error do you get?
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20292763
jkr: The code being called isn't managed C++ Why can't it stay put?
0
 
LVL 40

Accepted Solution

by:
evilrix earned 500 total points
ID: 20292780
Looking at the docs....

The function prototype is: -

FLAC__bool FLAC__stream_encoder_process_interleaved  (  FLAC__StreamEncoder *  encoder,  
  const FLAC__int32  buffer[],  
  unsigned  samples
 )  

So, calling it should be something like this...

FLAC__stream_encoder_process_interleaved(encoder, reinterpret_cast<FLAC__int32*>)(cBuffer), nBytesToAdd);

Working example...

void foo(const int[]){}

int main()
{
      char a[100];
      foo(reinterpret_cast<int *>(a));
      return 0;
}
0
 
LVL 8

Expert Comment

by:Wikkard
ID: 20292805
Have a look in the header file to see what FLAC__int32 actually is.
It will probably be just a synonym for 32bit unsigned integer or something.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20292894
>> What does 'array<Byte>^' do in standard C++ other than create an error message? ;o)
I'm just pointing out the code he is trying to interface to isn't managed code so it is as much a non managed code Q and it is a manage Q! You; however, are the administrator so, as you wish!
0
 
LVL 6

Author Comment

by:so3
ID: 20296964
thanks evilrix,

I will test it home, so you think that the procedure should be like this.

bool static FlacEncode(array<Byte>^ BytesToEncode,int nAudioBytesLeft)
                  {
                        unsigned char *cBuffer;
                        cBuffer =(unsigned char *)malloc(nAudioBytesLeft);
                       
                        for (int i =0; i < nAudioBytesLeft; ++i)
                              cBuffer[i]=BytesToEncode[i];
                 
                        while (nAudioBytesLeft > 0)
                        {
                              int nBytesToAdd = nAudioBytesLeft;

                              /* feed samples to encoder */
                              ok = FLAC__stream_encoder_process_interleaved(encoder, reinterpret_cast<FLAC__int32*>(cBuffer), nBytesToAdd);
                              nAudioBytesLeft -= nBytesToAdd;
                        }
                        return true;
                  }

In their example is like this(is reading from a wav file)
static FLAC__int32 pcm[READSIZE/*samples*/ * 2/*channels*/];


/* read blocks of samples from WAVE file and feed to encoder */
      if(ok) {
            size_t left = (size_t)total_samples;
            while(ok && left) {
                  size_t need = (left>READSIZE? (size_t)READSIZE : (size_t)left);
                  if(fread(buffer, channels*(bps/8), need, fin) != need) {
                        fprintf(stderr, "ERROR: reading from WAVE file\n");
                        ok = false;
                  }
                  else {
                        /* convert the packed little-endian 16-bit PCM samples from WAVE into an interleaved FLAC__int32 buffer for libFLAC */
                        size_t i;
                        for(i = 0; i < need*channels; i++) {
                              /* inefficient but simple and works on big- or little-endian machines */
                              pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8) | (FLAC__int16)buffer[2*i]);
                        }
                        /* feed samples to encoder */
                        ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, need);
                  }
                  left -= need;
            }
      }
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20297046
>> so you think that the procedure should be like this
My only assertion is that the mechanism I've suggested for casting should compile -- as to whether the cast is safe or not is another matter. The only guarantee you have when converting from one pointer to another is that you can safely convert back again. Any other usage of that point is undefined -- which doesn't mean it is unsafe, just that the standard doesn't define what behavior you can expect since it largely depends what you've converted from/to and what you plan to do with that converted pointer. Certainly reinterpret_cast is safer than a C style cast as it won't allow you to accidentally cast to a pointer type that is not compatible -- e.g. variable pointer to function pointer; where as a C style cast will.

http://msdn2.microsoft.com/en-us/library/e0w9f63b(VS.80).aspx

"The result of a reinterpret_cast cannot safely be used for anything other than being cast back to its original type. Other uses are, at best, nonportable."

NB. The same is true of C style casts

The example code seems overly complex in the elaborate way the casting is being done; however, I have no knowledge of this code-base so I wouldn't suggest it is wrong. I think, try the reinterpret_cast and if that work then great, if not try to analyze the example code to see why they have such an elaborate multi-casting construct.

Good luck.

-Rx.
0
 
LVL 6

Author Comment

by:so3
ID: 20299686
I've tested with your sugestion, i can compile it and id don't receive an error on first time but if i try it again i get error "atempted to read and write protected memory"

Can you please take a look at my code maybe you can give me a sugestion why this isn't working. It's all about the casts i think, but unfortunatly i don't know how to use them in c++. Also if you have time please take a look at the encoder example from FLAC at this link:

http://sourceforge.net/project/showfiles.php?group_id=13478&package_id=12677



My code:

bool static StartEncoder(System::String^ outputfile, int CompressionLevel,int rate, int bits, int channels)
                  {
                        char *  filename=(char*)(void*)Marshal::StringToHGlobalAnsi(outputfile->ToString());
                        
                        sample_rate = rate;
                        channels = channels;
                        bps = bits;
                        //total_samples = (((((((unsigned)buffer[43] << 8) | buffer[42]) << 8) | buffer[41]) << 8) | buffer[40]) / 4;
                        /* allocate the encoder */
                        if((encoder = FLAC__stream_encoder_new()) == NULL) {
                              return false;
                        }
                        ok &= FLAC__stream_encoder_set_verify(encoder, true);
                        ok &= FLAC__stream_encoder_set_compression_level(encoder, CompressionLevel);
                        ok &= FLAC__stream_encoder_set_channels(encoder, channels);
                        ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
                        ok &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
                        //ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples);

                        /* now add some metadata; we'll add some tags and a padding block */
                        if(ok) {
                              if(
                                    (metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
                                    (metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL ||
                                    /* there are many tag (vorbiscomment) functions but these are convenient for this particular use: */
                                    !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ARTIST", "Some Artist") ||
                                    !FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, /*copy=*/false) || /* copy=false: let metadata object take control of entry's allocated string */
                                    !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "YEAR", "1984") ||
                                    !FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, /*copy=*/false)
                              ) {
                                    fprintf(stderr, "ERROR: out of memory or tag error\n");
                                    ok = false;
                                    return false;
                              }

                              metadata[1]->length = 1234; /* set the padding length */

                              ok = FLAC__stream_encoder_set_metadata(encoder, metadata, 2);
                        }
                        /* initialize encoder */
                        if(ok) {
                              init_status = FLAC__stream_encoder_init_file(encoder, filename, progress_callback, /*client_data=*/NULL);
                              if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
                                    fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]);
                                    ok = false;
                                    return false;
                              }
                        }
                        return true;
            }


            bool static FlacEncode(array<Byte>^ BytesToEncode,int nAudioBytesLeft)
                  {
                        unsigned char *cBuffer;
                        cBuffer =(unsigned char *)malloc(nAudioBytesLeft);
                        
                        for (int i =0; i < nAudioBytesLeft; ++i)
                              cBuffer[i]=BytesToEncode[i];
                  
                        while (nAudioBytesLeft > 0)
                        {
                              int nBytesToAdd = nAudioBytesLeft;

                              /* feed samples to encoder */
                              ok = FLAC__stream_encoder_process_interleaved(encoder, reinterpret_cast<FLAC__int32*>(cBuffer), nBytesToAdd);
                              nAudioBytesLeft -= nBytesToAdd;
                        }
                        return true;
                  }

            bool static CloseEncoder()
            {
                  ok &= FLAC__stream_encoder_finish(encoder);

                  /* now that encoding is finished, the metadata can be freed */
                  FLAC__metadata_object_delete(metadata[0]);
                  FLAC__metadata_object_delete(metadata[1]);

                  FLAC__stream_encoder_delete(encoder);
                  encoder=NULL;
                  return ok;
            }
0
 
LVL 6

Author Comment

by:so3
ID: 20299810
Forget about the error on second time(it was from a bool value). Now i don't receive any error but the file is only 1.3k. It seems that only the header is written.
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 40

Expert Comment

by:evilrix
ID: 20300030
I'm being hassled to go out by my wife so I can't look right now but I can tell you there seems to be a memory leak in FlacEncode -- you malloc cBuffer but never free it.
0
 
LVL 6

Author Comment

by:so3
ID: 20300317
Thanks for the tip. you're right i've corrected the code with free(cBuffer).
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20302630
I think the simplest thing for you to do is use the debugger to step through the code. Put a break point in the part that writes out the bit that seems to be missing and when it's hit step into the code and see what's happening. If your break-point isn't hit this is probably the reason it's not writing :)
0
 
LVL 6

Author Comment

by:so3
ID: 20307834
I've tried this too. It steps through the writting code  and i don't receive any error. I'm so confused, i don't receive errors but the output code is only 1.3k.
could be about the casting or the problem is elsewhere?

I've noticed that i repeat the encoding without modifing the code the output size is changing 1.3k, 13k

If you have any ideas, please let me know.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20308207
Can you publish the full code here so I can download it and review it?

http://www.ee-stuff.com/

That might make this simpler :)
0
 
LVL 6

Author Comment

by:so3
ID: 20308550
Here is the link:
https://filedb.experts-exchange.com/incoming/ee-stuff/5676-Rippers.zip

I'm working with visual studio 2008 so the project is in 2008. the sample contains the project in C# which gets the wav bytes from a CD track and send to it to FlacWriter which is supposed to encode it. You have to attach the project JS.Flac to the main project.

I've played a little with the code and i think that the problem is in casting because i've the part of reading bytes from a file from their example and it works fine.
0
 
LVL 6

Author Comment

by:so3
ID: 20308560
static FLAC__byte buffer[READSIZE/*samples*/ * 2/*bytes_per_sample*/ * 2/*channels*/]; /* we read the WAVE data into here */

size_t left = (size_t)total_samples;
while(ok && left) {
size_t need = (left>READSIZE? (size_t)READSIZE : (size_t)left);
 if(fread(buffer, channels*(bps/8), need, fin) != need) {
 fprintf(stderr, "ERROR: reading from WAVE file\n");
 ok = false;
      }

Can  the above code reads from array<Byte>^ BytesToEncode instead of the file?
I think that might be the problem
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20477317
Objection: I answered the original question!

The question: "I'm trying to compress wave with FLAC codec but i don't know how to convert bytes to flac__int32. Here is the code i'm trying to make it work."

The answer: http://www.experts-exchange.com/Microsoft/Development/.NET/Visual_CPP/Q_22964276.html?cid=238#20292780

I also pointed out that just because I'd shown him how to perform the cast doesn't mean the cast is safe nor correct!

The OP then introduced a new problem that I was unable to diagnose, which was only identified once I helped him/her get the code to build!
0
 
LVL 6

Author Comment

by:so3
ID: 20477943
thanks for your help evilrix
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20477994
You are very welcome.
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

The following diagram presents a diamond class hierarchy: As depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourt…
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now