so3
asked on
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_proce ss_interle aved(encod er, (FLAC__int32*)&cBuffer[0], nBytesToAdd);
nAudioBytesLeft -= nBytesToAdd;
}
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_proce
nAudioBytesLeft -= nBytesToAdd;
}
return true;
}
What error do you get?
jkr: The code being called isn't managed C++ Why can't it stay put?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
It will probably be just a synonym for 32bit unsigned integer or something.
>> 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!
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!
ASKER
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_proce ss_interle aved(encod er, reinterpret_cast<FLAC__int 32*>(cBuff er), 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__int1 6)(FLAC__i nt8)buffer [2*i+1] << 8) | (FLAC__int16)buffer[2*i]);
}
/* feed samples to encoder */
ok = FLAC__stream_encoder_proce ss_interle aved(encod er, pcm, need);
}
left -= need;
}
}
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_proce
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__int1
}
/* feed samples to encoder */
ok = FLAC__stream_encoder_proce
}
left -= need;
}
}
>> 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.
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.
ASKER
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::Strin g^ outputfile, int CompressionLevel,int rate, int bits, int channels)
{
char * filename=(char*)(void*)Mar shal::Stri ngToHGloba lAnsi(outp utfile->To String());
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_v erify(enco der, true);
ok &= FLAC__stream_encoder_set_c ompression _level(enc oder, CompressionLevel);
ok &= FLAC__stream_encoder_set_c hannels(en coder, channels);
ok &= FLAC__stream_encoder_set_b its_per_sa mple(encod er, bps);
ok &= FLAC__stream_encoder_set_s ample_rate (encoder, sample_rate);
//ok &= FLAC__stream_encoder_set_t otal_sampl es_estimat e(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__META DATA_TYPE_ VORBIS_COM MENT)) == NULL ||
(metadata[1] = FLAC__metadata_object_new( FLAC__META DATA_TYPE_ PADDING)) == NULL ||
/* there are many tag (vorbiscomment) functions but these are convenient for this particular use: */
!FLAC__metadata_object_vor biscomment _entry_fro m_name_val ue_pair(&e ntry, "ARTIST", "Some Artist") ||
!FLAC__metadata_object_vor biscomment _append_co mment(meta data[0], entry, /*copy=*/false) || /* copy=false: let metadata object take control of entry's allocated string */
!FLAC__metadata_object_vor biscomment _entry_fro m_name_val ue_pair(&e ntry, "YEAR", "1984") ||
!FLAC__metadata_object_vor biscomment _append_co mment(meta data[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_m etadata(en coder, metadata, 2);
}
/* initialize encoder */
if(ok) {
init_status = FLAC__stream_encoder_init_ file(encod er, filename, progress_callback, /*client_data=*/NULL);
if(init_status != FLAC__STREAM_ENCODER_INIT_ STATUS_OK) {
fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitSta tusString[ init_statu s]);
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_proce ss_interle aved(encod er, reinterpret_cast<FLAC__int 32*>(cBuff er), nBytesToAdd);
nAudioBytesLeft -= nBytesToAdd;
}
return true;
}
bool static CloseEncoder()
{
ok &= FLAC__stream_encoder_finis h(encoder) ;
/* now that encoding is finished, the metadata can be freed */
FLAC__metadata_object_dele te(metadat a[0]);
FLAC__metadata_object_dele te(metadat a[1]);
FLAC__stream_encoder_delet e(encoder) ;
encoder=NULL;
return ok;
}
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::Strin
{
char * filename=(char*)(void*)Mar
sample_rate = rate;
channels = channels;
bps = bits;
//total_samples = (((((((unsigned)buffer[43]
/* allocate the encoder */
if((encoder = FLAC__stream_encoder_new()
return false;
}
ok &= FLAC__stream_encoder_set_v
ok &= FLAC__stream_encoder_set_c
ok &= FLAC__stream_encoder_set_c
ok &= FLAC__stream_encoder_set_b
ok &= FLAC__stream_encoder_set_s
//ok &= FLAC__stream_encoder_set_t
/* now add some metadata; we'll add some tags and a padding block */
if(ok) {
if(
(metadata[0] = FLAC__metadata_object_new(
(metadata[1] = FLAC__metadata_object_new(
/* there are many tag (vorbiscomment) functions but these are convenient for this particular use: */
!FLAC__metadata_object_vor
!FLAC__metadata_object_vor
!FLAC__metadata_object_vor
!FLAC__metadata_object_vor
) {
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_m
}
/* initialize encoder */
if(ok) {
init_status = FLAC__stream_encoder_init_
if(init_status != FLAC__STREAM_ENCODER_INIT_
fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitSta
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_proce
nAudioBytesLeft -= nBytesToAdd;
}
return true;
}
bool static CloseEncoder()
{
ok &= FLAC__stream_encoder_finis
/* now that encoding is finished, the metadata can be freed */
FLAC__metadata_object_dele
FLAC__metadata_object_dele
FLAC__stream_encoder_delet
encoder=NULL;
return ok;
}
ASKER
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.
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.
ASKER
Thanks for the tip. you're right i've corrected the code with free(cBuffer).
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 :)
ASKER
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.
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.
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 :)
http://www.ee-stuff.com/
That might make this simpler :)
ASKER
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.
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.
ASKER
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
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
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: https://www.experts-exchange.com/questions/22964276/Convert-bytes-to-flac-int32.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!
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: https://www.experts-exchange.com/questions/22964276/Convert-bytes-to-flac-int32.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!
ASKER
thanks for your help evilrix
You are very welcome.