C++ assignment with .mp3 files

In summary, I am trying to read the first four "bytes" of the file and put them into an (unsigned char) array. I am not really sure if I am reading from the file or not - I can't tell from these characters that I print out. Does this look right to you?In summary, I am trying to read the first four bytes of the file and put them into an unsigned char array. I am not sure if I am reading from the file or not - I can't tell from these characters. Does this look right to you?
  • #1
Math Is Hard
Staff Emeritus
Science Advisor
Gold Member
4,652
37
OK, so I've got this wacky homework assignment that involves reading stuff out of a .mp3 file. Just to get started, I am attempting to read the first four "bytes" of the file and put them into an (unsigned char) array. I am not really sure if I am reading from the file or not - I can't tell from these characters that I print out. Does this look right to you?

Code:
# include <iostream>
# include <fstream>

using namespace std;
typedef unsigned char byte;

int main()
{
	cout<< "enter the mp3 filename (including the .mp3): "<< endl;
	char buff[100];
	cin.getline(buff,100);
	byte array[4];
	ifstream in(buff, ios::in|ios::binary);

	if(!in)
	{
		cout <<"no file found" << endl;
		exit(1);
	}

	for (int i = 0; i<4;++i)
	{
		char ch;
		in.get(ch);
		array[i] = ch;
	}

	in.close();

	for (int j = 0; j<4;++j)
		cout << array[j];
	cout <<endl;

	return 0;
}

Here's the assignment I am working on by the way.
http://www.math.ucla.edu/~rclark/10a.1.05w/hw5/hw5.html
The teacher has written most of this for us and there's really just a few functions I have to write but I have been a nervous wreck trying to figure this out. I thought I better go ahead and post since I know I'll be working on it all weekend. :frown:
More questions coming soon.
 
Last edited by a moderator:
Physics news on Phys.org
  • #2
Ok the code looks fine to me.
You should be able to check to see if you are reading the right stuff by opening up the mp3 file with notepad, vi, wordpad, and checking to see if the first three chars are the same. This has worked for me in the past.

I would also use in.is_open() rather then !in. In your library are these the say thing?
 
Last edited:
  • #3
Also:

Save a file that you know what's in it. You know, enter some text in a word processor, save as a .txt file, then read it in with your program and verify it's getting the data.

And, well, nice if you can run it in a debugger like Microsoft Visual C++ environment.
 
  • #4
Thanks for the hints, y'all. I am so lost on this assignment for some reason!
 
  • #5
MIH,

Do you have to use the silly C++ stream library functions to do this assignment? They are reeeeeally not designed nor appropriate for reading binary files.

You'd be much better off just using the fopen() and fread() functions to directly read four bytes into an array. In fact, your code will fail if one of the first four characters is a newline character. Your call to getline() will then return fewer than four bytes, and your code with throw an exception before you read all four.

http://www.opengroup.org/onlinepubs/007908799/xsh/fopen.html
http://www.opengroup.org/onlinepubs/007908799/xsh/fread.html

- Warren
 
  • #6
Hi Warren,

yeah, I believe I am pretty much stuck with this. actually the teacher has already written http://www.math.ucla.edu/~rclark/10a.1.05w/hw5/hw5.cpp and he uses <fstream> - our assignment is just to write some of the functions in the program. I believe the main point of this assignment was to introduce us to to using ifstream and ofstream.
Thanks for telling me about those functions though. I will probably need them in the future. It does sound like that would be a better way to go for working with binary files.
 
Last edited by a moderator:
  • #7
Don't forget about the istream.read method, which is directly analogous to fread.
 
  • #8
ok, here come some questions. The first one is about writing these "bytes" in my array out to a binary file.
If I make an ofstream variable called "out" can I just do this?

out.put(array[someIndexNumber]);

when I take the stream in, I capture each "byte" as a character and put it into the unsigned char array. I am not sure what I need to do before sending it back out to a different binary file.
Thanks for your advice!
 
  • #9
I also asked plover this question earlier in a PM. I'll post it here in case he wants to reply in this post:
*************************************************
I am confused about this "string" data type in the return type of the function below which I am supposed to complete:

/* Instructions: if i<0, returns the string "0". for all others, it returns the string version of i. */

string int2string(int i)
{
// write this stuff
}

OK, I am going to guess and say we're able to use this string datatype because we're using the string class - we didn't cover very much about this yet. But I don't know how to use it. Is it like a char array?

If it's like an array, then I am confused about using it for a return type. :confused:
 
  • #10
Do you mean the standard std::string class? man std::string may help you.
 
  • #11
The string datatype is part of the Standard Template Library. You can wrap a char* into a std::string with one of the std::string constructors like this:

char buf[100];
sprintf(buf, "%d", i);
return string str(buf);

- Warren
 
  • #12
Thanks, Warren. I'll play around with that. So I guess regular old arrays can't be return types but strings can?
 
  • #13
Math Is Hard said:
So I guess regular old arrays can't be return types but strings can?
You can return an array that is created in a function, but it must have been created on the heap with malloc() and you have to remember to free this memory when the array is no longer useful.

Using an object just makes this whole process conceptually simpler. (Though if done without a little care, it can also make the process a lot less efficient.) There ought to be a reference section on the string class in your book.

danne89 is referring to the unix documentation system (known as 'man pages' as the docs are accessed through command called 'man' (for manual)).

The string class while part of the C++ Standard Library, is not technically part of the C++ Standard Template Library (though it is closely related).

While it is certainly possible to initialize a string with a char array, this does not simply create an object wrapper around the array—the string object will create it's own storage space and copy the array. One useful way to create a string from a character is to use the constuctor that's intended to create a string consisting of n copies of a given character:
Code:
char c = 'x';
string s(1, c);
Also the 'return' line in chroot's example should be:
Code:
return string(buf);
When returning an object, applying 'return' to the result of a constructor call like this is often the way to go.

As to the earlier question, if you are writing to your output file one byte at a time, using the 'put' member function is just fine.
 
Last edited:
  • #14
Thanks so much, plover. I am having pretty good luck with the string constructor. Almost done! Then the debugging begins - pleh! :yuck:
I have to whip up a little something to take an integer and turn it into an array of characters, (will convert it to a string afterwards) but I did something similar in another assignment so hopefully I can figure that out. I don't suppose there's any slick little function that would do that for me? nah, probably not. I couldn't find one anyway.
thanks again. I'll let you know how I make out. :biggrin:
 
  • #16
Thanks for that link, Warren. That was really extensive! Much more than what is in my book.

I am still stuck on a little problem. I can take and integer like 155 and convert it to an int array of single digit integers 1,5,5, but I am not sure how to go from there to convert it into an array of characters '1','5', and '5'. This is what I want to do before I construct the string.

I found some suggestions on the internet for taking an integer and converting it directly to a character array using itoa(), but my version of C++ didn't like that. :frown:

If I could just figure out how to take a single digit integer and convert it to a single character, that would be helpful, but I am unable to figure that out from my book, or from the the docs I have found on the internet.
Any advice? Thanks.
 
  • #17
If you can't make itoa work, then just use sprintf. Do not attempt to do the conversion to characters yourself, it's a total waste of time.

By the way, the ASCII codes for the numerals 0-9 are 0x30 through 0x39. If you want to convert a single-digit number to its ASCII equivalent, just add 0x30 to it and cast it to char.

- Warren
 
  • #18
To convert a single digit, you can always do this:
Code:
int d = getDigit();
char c = '0' + d;
But the entire number can be converted to a char array at once using the C 'sprintf' function from <cstdio> (as in chroot's example above), or directly to a string using C++ <sstream> library.

edit: oops, chroot got here first...
 
Last edited:
  • #19
Thanks for the help, chroot and plover! :smile:
 
  • #20
# include <bighugs>
HOORAYYYY! It works!
*jumps for joy*
I have the whole program working now. (well, I haven't compiled it in .NET version of MS VC++ but all is A-OK here in version 6, and I worked really hard to avoid any incompatibility issues that have given me headaches before.)
Couldn't have done it without y'all. Thanks again! :smile:
<hug><hug><hug>
 
  • #21
Way to go, MIH. :smile:

- Warren
 
  • #22
Maybe in the future you will extend the program to 'interpret' that file, that is, produce sound :wink:
 
  • #23
GRRRRR! Visual C++ .NET!

I am getting another one of those frustrating error C2668 "ambiguous call to overloaded function" messages when I try to build this in MS VC++ .NET. This is the offending line:

int expo = static_cast<int>(log10(i));

Am I using static_cast incorrectly? i is an integer here. This compiles just fine in version 6.

Thanks,
MIH
 
  • #24
The log10 function is overloaded. There a log10(int) and a log10(double) and so on. You have to explicitly tell the compiler which one you want to use.

Try:

int expo = (int) log10( (int) i );

- Warren
 
  • #25
The C++ standard specifies 3 different versions of most math functions for the 3 floating point types, e.g.:
Code:
float log10(float x);
double log10(double x);
long double log10(long double x);
Since your argument is an int the compiler does not know which one to use. (Also note that the error message refers to a function—static_cast<> and other cast expressions are not considered functions.)

There are two ways to deal with this.

One is to put a second type cast on the argument:
Code:
int expo = static_cast<int>(log10(static_cast<double>(i)));
(As a rule always use doubles for floating point calculations unless there is an explicit reason not to.)

The other would be to declare your variable i as a double instead of an int. Whether this second version is appropriate depends on where the value for i is coming from.

The first approach would probably be the recommended one.
 
  • #26
Heh, I have no idea why I thought there was an int version of log10, nor why I thought casting an int to an int would make any difference. Brain fart.

- Warren
 
  • #27
Gosh! What a pain in the butt just to do one simple thing! I casted the "i" as double and all is OK now.
Thanks for the help!
 

1. How do I open and read an .mp3 file in C++?

In order to open and read an .mp3 file in C++, you will need to use the ifstream class from the fstream library. You can use the open() function on the ifstream object to specify the file path and then read the file using the read() function.

2. Can I write data to an .mp3 file using C++?

Yes, it is possible to write data to an .mp3 file using C++. You can use the ofstream class from the fstream library to create and write data to a file. Make sure to specify the file path and use the write() function to write the data to the file.

3. How can I manipulate the audio data in an .mp3 file using C++?

In order to manipulate the audio data in an .mp3 file using C++, you will need to use a library that supports audio manipulation, such as libmpg123 or TagLib. These libraries provide functions for reading, writing, and manipulating audio data in various formats, including .mp3 files.

4. Are there any specific libraries or APIs for working with .mp3 files in C++?

Yes, there are several libraries and APIs specifically designed for working with .mp3 files in C++. Some popular options include libmpg123, TagLib, and MadPlay. These libraries provide a variety of functions for reading, writing, and manipulating audio data in .mp3 files.

5. Can I convert an .mp3 file to another audio format using C++?

Yes, it is possible to convert an .mp3 file to another audio format using C++. You can use a library like FFmpeg or libmp3lame to convert the file. These libraries provide functions for converting audio data from one format to another, including .mp3 to other formats and vice versa.

Similar threads

  • Programming and Computer Science
Replies
6
Views
8K
Replies
10
Views
958
  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
Replies
30
Views
2K
  • Programming and Computer Science
2
Replies
66
Views
4K
  • Programming and Computer Science
Replies
5
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
944
  • Programming and Computer Science
3
Replies
75
Views
4K
  • Programming and Computer Science
2
Replies
65
Views
5K
  • Programming and Computer Science
Replies
12
Views
2K
Back
Top