|
Hi Ruslan,
Great article and good code examples. I ran your program on my computer and its working perfectly fine. However it would be great if we could avoid going to the dos prompt and then running the program i.e. when I want to run the application then I can directly launch the .exe file and it displays all the devices and lines present on the system. After that I could select any of the line and start recording. I was trying out this for myself but could not do it( I am very poor at coding ). Hope you could help me with this..Thanks.
|
|
|
|
|
Hi,
You suggest having a GUI for this application? Well, idea is all these come with open sources. If I implement a GUI, I can sell it for (e.g.) 10$ per unit. Since Lame is a light GPL, I can do that with no problems, except I must mention somewhere (visible in GUI) that I am using Lame (with the URL to their site). Or someone else can do that with my code , which will definitely be "not at least kind of effort" if I do GUI as well. I have seen lots of similar applications and people buying them.
So, this is the main reason I didn't do GUI. Plus, if you know a bit of C# or Visual Basic and C/C++, you can wrap my sources in a DLL and use C#/VB for the GUI stuff only, that's really half a day work maximum. Otherwise, in the ZIP with binaries I included a BAT file which you can use as a fast start option.
Regards,
Ruslan
|
|
|
|
|
Ya, you are right Ruslan. But how do I get rid of the dos prompt. I mean to say, I dont need a complete GUI but what I need is that once I launch the program from Debug folder, the application just reads the WaveInDevice and displays the list of all the available lines. I just select one line and start recording. I tried to change the code but its too complex for me to handle.
Read this scenario
I launch the application and it displays the WaveInDevice and the lines on this device.Now I select one line and start recording from that point of time on that line.
I appreicate your comments.
|
|
|
|
|
I see what you mean. This reminds me of the university ages ... "Please specify the array size:" ... "Please enter 1st element:" ... etc . Well, to be honest, I haven't thought about this. Idea of the article was to have as set of usable classes, a simple application as a proof of concept and, next, to move to the internet streaming ideas. It isn't difficult at all to implement your scenario, but very annoying actually . That's right, very annoying because:
1. Application must handle user input - if something is wrong, then ask user to re-enter again.
2. Some combinations of bitrate and simple rate may not be accepted by Lame engine. So, ask user to re-specify again.
3. Combine user input and command line parameters. What is not set in command line – ask user to specify. Or leave default, but default options (e.g. Volume level = 0) may not work perfectly for all the PC configurations (as I wrote in the article).
Well, the code must be re-thought as well, to make it look nice. So, definitely it's easier
- to have a GUI or
- take Linux/Unix approach where command line tool has a bunch of command line options and works "from the top to the bottom, if something is wrong – report and quit". Easier to code, less errors and if user finds the best combination of command line options – they create a shell script which will make life easier (approach I usually take ).
I don't say no, but I promise to think about
Regards,
Ruslan
|
|
|
|
|
I got around the command prompt. Now I am able to disply the Device name and the lines. nothing much to do in it. Great work Ruslan. 3 cheers to you.
|
|
|
|
|
You are welcome
Regards,
Ruslan
|
|
|
|
|
Hai rtybase
I found ur article intresting but if u feel free to explain how this process Recording the sound from the soundcard little bit more and if you can provide some helpfull link i would be thankfull.
jobythomas24@gmail.com
|
|
|
|
|
Hi,
Well, one of the ideas of this article is to present some classes that help with recording from the sound card. You can use them directly, no problems. However, if you want to dig deeper inside this topic, I posted sources as well and I did my best to comment them. But, as a good start to understand the entire "kitchen behind" I would recommend these links:
http://www.borg.com/~jglatt/tech/lowaud.htm
http://www.borg.com/~jglatt/tech/mixer.htm
Once you understand the concepts, check the sources inside "waveIN_simple.h" file. Start with the constructor "CWaveINSimple::CWaveINSimple(...)", check "CWaveINSimple::_Start(...)" method next and, at the end, check "CWaveINSimple::waveInProc(...)" method. This is the core and code for those methods is not complex.
Regards,
Ruslan.
|
|
|
|
|
hai Ruslan Ciurca
Fine article i included ur class in my app and i was able to get stereo mix in dialog based app i was looking for it for a long time thanks once more
jobythomas24@gmail.com
|
|
|
|
|
That's a really good little program but I'm wondering if you would give me a pointer in the right direction please?
I program in VB.NET and am a bit poor on C++/C#. I understand most of what you did in the code but you have put on the bottom that you could modify the code:
[quote]
If you wish, you can adjust the code, so application will support two more extra command line options, e.g. "-bitrate" to indicate at what bitrate to perform MP3 encoding (my demo is encoding at 128Kbps) and "-volume" to manage Line's volume from the command line (my application is setting it to "50%", but ... see "Remark 1" above)[/quote]
I have REALLY tried (for a fair few days now!) to be able to implement these but have been unsuccesful and I would appreciate just a pointer if possible.
I was also wondering if the sample rate can be changed as well from 44.1kHz
Thanks very much in advance
Rob
|
|
|
|
|
Ok, regarding volume. In the "mp3_stream.cpp" you can find the lines:
mixerline.UnMute();
mixerline.SetVolume(50);
mixerline.Select();
mixer.Close();
"mixerline.SetVolume(50);" is the one which sets the volume to 50%. So, this is easy.
Regarding bitrate, in the same file, see:
class mp3Writer: public IReceiver {
private:
CMP3Simple m_mp3Enc;
FILE *f;
public:
mp3Writer(): m_mp3Enc(128) {
f = fopen("music.mp3", "wb");
if (f == NULL) throw "Can't create MP3 file.";
};
...
You can adjust the contructor of the "mp3Writer" class as follows:
mp3Writer(unsigned int bitrate = 128): m_mp3Enc(bitrate) {
f = fopen("music.mp3", "wb");
if (f == NULL) throw "Can't create MP3 file.";
};
so, you can build instances of "mp3Writer" by indicating required bitrate as well (128 still default).
Regarding sample rate, see "INCLUDE\mp3_simple.h". Costructor of the class "CMP3Simple":
CMP3Simple(unsigned int nBitRate, unsigned int nInputSampleRate = 44100,
unsigned int nOutSampleRate = 0);
Also there you will find a description for each parameter, but just a short remark, "nInputSampleRate" is the sample rate of the PCM to be encoded (!!!) where "nOutSampleRate" is the final rate (== 0 says to not re-sample). If you need to re-sample, better to use that parameter. So, you can change constructor of the class "mp3Writer" as (final version) follows:
mp3Writer(unsigned int bitrate = 128, unsigned int finalSimpleRate = 0):
m_mp3Enc(bitrate, 44100, finalSimpleRate) {
f = fopen("music.mp3", "wb");
if (f == NULL) throw "Can't create MP3 file.";
};
Coming back to the "mp3_stream.cpp", now you can change the code like:
mp3Wr = new mp3Writer(64, 32000);
and you will get the output at 64Kbps and 32KHz.
I hope this will help. If not, I will set a new version of the sources and binaries with this article, but, not earlier than after next week (in a business trip now).
|
|
|
|
|
Thanks very much for the quick reply. I will look at this over the next couple of days and let you know how I get on. A brief look at it looks like it will answer my questions.
Cheers
Rob
-- modified at 11:01 Wednesday 8th November, 2006
|
|
|
|
|
I updated the article, source code and demo project links. It supports additional 3 parameters now. Feel free to use it
Ruslan
|
|
|
|
|
Hi Ruslan,
thanks very much for the updated file. I had actually battled through and written my own code to provide these functions but realise after looking at yours that it was a little messy - probably because I'm not used to C!! One thing that has occurred in both the code I wrote and the new code that you have written is that changing the sample rate doesn't affect the size of the recording i.e. a recording in 44100Hz produces the same file size as one recorded in 8000hz. I have been trying to sort this out but have been unable to so far. Is it because of this?
[code]
virtual void ReceiveBuffer(LPSTR lpData, DWORD dwBytesRecorded) {
BYTE mp3Out[44100 * 4];
DWORD dwOut;
m_mp3Enc.Encode((PSHORT) lpData, dwBytesRecorded/2, mp3Out, &dwOut);
fwrite(mp3Out, dwOut, 1, f);
};
[/code]
any help with this much appreciated.
Thanks again
Rob
|
|
|
|
|
Hello Rob,
Everything is fine with that code. It just sends the buffer with PCM (lpData) data, indicating the size (dwBytesRecorded), to the Lame encoder. Since PCM buffer is in BYTEs and Lame API requires SHORTs, code just casts BYTEs to SHORTs (pointers are meant of course) and set the size to dwBytesRecorded/2 (2* BYTE = SHORT). Recording is in stereo mode, so dwBytesRecorded is divisible by 2.
Lame encoder copies encoded data to the mp3Out buffer and sets the buffer size to the dwOut. Exactly dwOut bytes from the mp3Out buffer are written to the MP3 output file due to
fwrite(mp3Out, dwOut, 1, f);
Back to your question, there is a big difference between bitrate and sample rate so far. To predict the output file size having the bitrate (br) and playing time (t, sec) use the formula:
file_size = (br * t) / 8;
For more details see:
- few details regarding above formula on http://www.mp3-converter.com/bitrates.htm
- same formula on http://www.codeproject.com/audio/mpegaudioinfo.asp
- http://webhome.idirect.com/~nuzhathl/mp3-faq.html#ques17
- http://webhome.idirect.com/~nuzhathl/mp3-faq.html#ques97
- http://groups.google.co.uk/group/alt.music.mp3/browse_thread/thread/c89578e645572864/cb2ce06e13a32b14%23cb2ce06e13a32b14
So far, there is nothing about sample rate in that formula. All goes to the internal encoding algorithm of the Lame, where simple rate only affect the quality, not the size.
Another remark is; if to use Lame pre-settings, you will see a dependency picture like:
- if setting 128kbps => Lame will set sample rate to 44.1Khz
- if setting 96kbps => Lame will set sample rate to 32Khz
- if setting 64kbps => Lame will set sample rate to 24Khz
- if setting 32kbps => Lame will set sample rate to 16Khz
...
All this is done for the best MP3 quality. Very amazing, but with (e.g.) 96kbps/32Khz you may (but not as a rule) get a better MP3 sound quality than with 96kbps/44.1Khz due to different compressions (as the final MP3 file size will be the same). See the logic below:
1) 96Kbps/32Khz => 96Kbps = 12Kbytes/sec, which decoded should give 32Khz, 16 bits, stereo PCM sound (32000 * 16/8 * 2 = 128000 Bytes/sec = 125 Kbyte/sec). At the end we have 12Kbytes MP3 decompressed to 125Kbytes PCM, all per second.
2) 96Kbps/44.1Khz => 96Kbps = 12Kbytes/sec, which decoded should give 44.1Khz, 16 bits, stereo PCM sound (44100 * 16/8 * 2 = 176400 Bytes/sec ~ 172 Kbyte/sec). At the end we have 12Kbytes MP3 decompressed to 172Kbytes PCM, all per second.
96Kbps/32Khz: 12Kbytes MP3 <-> 125Kbytes PCM
96Kbps/44.1Khz: 12Kbytes MP3 <-> 172Kbytes PCM
So, 96Kbps/44.1Khz uses a "harder" compression than 96Kbps/32Khz.
Obvious question would be why not 96Kbps/24Khz? And the answer would be; 24Khz is a lower quality than 32Khz. So 96Kbps/32Khz seems to be the optimal compression-quality value for the 96Kbps bitrate.
Thanks for this question; I have discovered few interesting things for myself too
Regards,
Ruslan.
|
|
|
|
|
thanks again for your quick reply and really appreciate your help. I'm going to check out the links you supplied in your reply now.
Keep up the good work
Rob
|
|
|
|
|
nice work... works great...
how can i use your functions to play a mp3-file?
|
|
|
|
|
Well, you can't, since they do just recording (from Wave In) and encoding (as title of the article states). If you need to implement playing from your application, I recommend you to check http://www.arbingersys.com/madxlib.html. You can also download "Aumplib" from their site (http://www.arbingersys.com/concerns.html), it's a nice suite of classes and an application for converting from/to different audio formats (in C# however). Idea is, with "madxlib" you can decode MP3 and obtain raw PCM sound which you can play through Wave Out device. Problem is, their decoder may crash if "MP3 file" is not a valid MP3 file. "Aumplib" has a nice class "MP3Check.cs" which you can use as a "how to" to validate MP3 files. Other way would be to play via DirectSound. I haven't implemented decoding because I use these (from the article) classes for MP3 streaming only, where as a client application can be considered WinAmp or Windows Media Player.
-- modified at 6:48 Monday 18th September, 2006
|
|
|
|
|
Hello rtybase
Could you write a few lines to explain what kinds of entry should be made on the command line
of your console demo application, in order to start a recoding of MP3/WMA files from a microphone
(and else where, e.g., a DVD playing on the same PC)? It will be of great help for understanding
and using your code, at least in the initial stage.
Thank you for the nice code, it will sure be very useful for quite a few who check CodeProject regularly.
|
|
|
|
|
Done. I updated article and included few comments on using demo application. Thanks for pointing me on this by the way.
|
|
|
|
|