Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 537
  • Last Modified:

Convert bytes to flac_int32

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
so3
Asked:
so3
  • 10
  • 8
1 Solution
 
evilrixSenior Software Engineer (Avast)Commented:
What error do you get?
0
 
evilrixSenior Software Engineer (Avast)Commented:
jkr: The code being called isn't managed C++ Why can't it stay put?
0
 
evilrixSenior Software Engineer (Avast)Commented:
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
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
WikkardCommented:
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
 
evilrixSenior Software Engineer (Avast)Commented:
>> 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
 
so3Author Commented:
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
 
evilrixSenior Software Engineer (Avast)Commented:
>> 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
 
so3Author Commented:
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
 
so3Author Commented:
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
 
evilrixSenior Software Engineer (Avast)Commented:
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
 
so3Author Commented:
Thanks for the tip. you're right i've corrected the code with free(cBuffer).
0
 
evilrixSenior Software Engineer (Avast)Commented:
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
 
so3Author Commented:
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
 
evilrixSenior Software Engineer (Avast)Commented:
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
 
so3Author Commented:
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
 
so3Author Commented:
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
 
evilrixSenior Software Engineer (Avast)Commented:
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
 
so3Author Commented:
thanks for your help evilrix
0
 
evilrixSenior Software Engineer (Avast)Commented:
You are very welcome.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 10
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now