Find the uda1341 driver on the internet, compile it into the uda1341.ko module, and open the Kernel configuration menu.
Device Drivers --->
Sound --->
<M> sound card support
Make modules generates the soundcore. Ko module. Load the two modules to play the audio.
After carefully reading the uda1341 driver, we found that only 16 bits of audio can be played.
Convert to dual-channel when copying to the driver. Therefore, we recommend that you select 16-bit dual-channel WAV audio.
First, let's take a look at the wav file format. The front part is some audio information, which can be read as a parameter.
A wave file is composed of several chunks. According to the location where the file appears, including: Riff Wave
Chunk, format chunk, fact chunk (optional), data chunk. For details, see:
------------------------------------------------
| Riff wave chunk |
| Id = 'riff' |
| Rifftype = 'wave '|
------------------------------------------------
| Format chunk |
| Id = 'fmt' |
------------------------------------------------
| Fact chunk (optional) |
| Id = 'fact' |
------------------------------------------------
| Data chunk |
| Id = 'data' |
------------------------------------------------
Figure 1 example of chunk in WAV format
Riff wave chunk
========================================
| Bytes | specific content |
========================================
| ID | 4 bytes | 'riff' |
----------------------------------
| Size | 4 bytes |
----------------------------------
| Type | 4 bytes | 'wave '|
----------------------------------
Figure 2 riff wave chunk
Use 'riff' as the marker, followed by the size field. The size is the size of the whole WAV file minus the number of bytes occupied by ID and size, that is, filelen-8 = size. Then the type field, which is 'wave ', indicates a WAV file.
The structure is defined as follows:
Struct riff_header
{
Char szriffid [4];
DWORD dwriffsize;
Char szriffformat [4];
};
Format chunk
========================================================== ======================================
| Number of bytes | specific content |
========================================================== ======================================
| ID | 4 bytes | 'fmt' |
--------------------------------------------------------------------
| Size | 4 bytes | if the value is 16 or 18, the last information is appended. |
--------------------------------------------------------------------
| Formattag | 2 bytes | encoding method, generally 0x0001 |
--------------------------------------------------------------------
| Channels | 2 bytes | Number of audio channels; values: 1 (Single Channel) and 2 (dual channel) |
--------------------------------------------------------------------
| Samplespersec | 4 bytes | sampling frequency |
--------------------------------------------------------------------
| Avgbytespersec | 4 bytes | required bytes per second |
--------------------------------------------------------------------
| Blockalign | 2 bytes | data block alignment unit (number of bytes per sample, audio channel * sampling bit/8) |
--------------------------------------------------------------------
| Bitspersample | 2 bytes | Number of sampled bits |
--------------------------------------------------------------------
| 2 bytes | additional information (optional, which can be determined by size) |
--------------------------------------------------------------------
Figure 3 Format chunk
Use 'fmt' as the flag. Generally, the size is 16, and the last additional information does not exist. If the size is 18
Then, two additional bytes are added. These two bytes are contained in the WAV format made mainly by some software.
Additional information.
The structure is defined as follows:
Struct fmt_block
{
Char szfmtid [4];
DWORD dwfmtsize;
Wave_format wavformat;
};
Struct wave_format
{
Word wformattag;
Word wchannels;
DWORD dwsamplespersec;
DWORD dwavgbytespersec;
Word wblockalign;
Word wbitspersample;
};
Fact chunk
========================================
| Bytes | specific content |
========================================
| ID | 4 bytes | 'fact' |
----------------------------------
| Size | 4 bytes | the value is 4. |
----------------------------------
| Data | 4 bytes |
----------------------------------
Figure 4 fact chunk
Fact Chunk is an optional field. Generally, when a WAV file is converted from some software, it contains the chunk.
The structure is defined as follows:
Struct fact_block
{
Char szfactid [4];
DWORD dwfactsize;
};
Data chunk
========================================
| Bytes | specific content |
========================================
| ID | 4 bytes | 'data' |
----------------------------------
| Size | 4 bytes |
----------------------------------
| Data |
----------------------------------
Figure 5 Data chunk
The data chunk header structure is defined as follows:
Struct data_block
{
Char szdataid [4];
DWORD dwdatasize;
};
The data Chunk is the place where the wav data is actually stored. 'data' is used as the chunk identifier. Then
Data size. Followed by WAV data. Based on the number of channels in the format Chunk and the number of sampling bits,
The bit location of Wav data can be divided into the following forms:
---------------------------------------------------------------------
| Mono | sampling 1 | sampling 2 | sampling 3 | sampling 4 |
| --------------------------------------------------------
| 8-bit quantization | channel 0 | channel 0 | channel 0 | channel 0 |
---------------------------------------------------------------------
| Dual-channel | sampling 1 | sampling 2 |
| --------------------------------------------------------
| 8-bit quantization | channel 0 (left) | channel 1 (right) | channel 0 (left) | channel 1 (right) |
---------------------------------------------------------------------
| Sampling 1 | sampling 2 |
| Single channel | --------------------------------------------------------
| 16-bit quantization | channel 0 | channel 0 | channel 0 | channel 0 |
| (Low byte) | (high byte) |
---------------------------------------------------------------------
| Sample 1 |
| Dual-channel | --------------------------------------------------------
| 16-bit quantization | channel 0 (left) | channel 0 (left) | channel 1 (right) | channel 1 (right) |
| (Low byte) | (high byte) |
---------------------------------------------------------------------
Figure 6 bit location arrangement of Wav data
Use ultraedit to open the wav file of the XP shutdown sound. You can see these parameters.
The three most important parameters are the number of audio_channels channels, the number of audio_fmt sampling digits, and the audio_rate sampling frequency. In this way, you need to send the data (sampling frequency × sampling digits × channels)/8 bytes to uda1341 through the IIS interface.
The following is a C program for playing wav files on the Internet. You can play the files on the arm with a slight modification. Here I already know the parameter, so read-only skipping is not used.
# Include <unistd. h>
# Include <fcntl. h>
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <sys/IOCTL. h>
# Include <stdlib. h>
# Include <stdio. h>
# Include <string. h>
# Include <Linux/Soundcard. h>
# Define open_dsp_failed 0x00000001/* Open DSP failed! */
# Define samplerate_status 0x00000002/* samplerate status failed */
# Define set_samplerate_failed 0x00000003/* Set samplerate failed */
# Define channels_status 0x00000004/* channels status failed */
# Define set_channels_failed 0x00000005/* set channels failed */
# Define fmt_status 0x00000006/* FMT status failed */
# Define set_fmt_failed 0x00000007/* Set FMT failed */
# Define open_file_failed 0x00000008/* opem filed failed */
Int s32410_audio_play (char * pathname, int nsamplerate, int nchannels, int FMT)
{
Int dsp_fd, mix_fd, status, ARG;
Dsp_fd = open ("/dev/sound/DSP", o_rdwr);/* Open DSP pay attention to the device address */
If (dsp_fd <0)
{
Return open_dsp_failed;
}
Arg = nsamplerate;
Status = IOCTL (dsp_fd, sound_pcm_write_rate, & Arg);/* Set samplerate */
If (status <0)
{
Close (dsp_fd );
Return samplerate_status;
}
If (Arg! = Nsamplerate)
{
Close (dsp_fd );
Return set_samplerate_failed;
}
Arg = nchannels;/* set channels */
Status = IOCTL (dsp_fd, sound_pcm_write_channels, & Arg );
If (status <0)
{
Close (dsp_fd );
Return channels_status;
}
If (Arg! = Nchannels)
{
Close (dsp_fd );
Return set_channels_failed;
}
Arg = FMT;/* Set bit FMT */
Status = IOCTL (dsp_fd, sound_pcm_write_bits, & Arg );
If (status <0)
{
Close (dsp_fd );
Return fmt_status;
}
If (Arg! = FMT)
{
Close (dsp_fd );
Return set_fmt_failed;
}/* The above three important parameters are set to 44100 2 16 by default */
File * file_fd = fopen (pathname, "R ");
If (file_fd = NULL)
{
Close (dsp_fd );
Return open_file_failed;
}
Int num = 3 * nchannels * nsamplerate * FMT/8; // number of bytes written each time
Int get_num; // In fact, it is best to write an integer multiple of 8192 bytes each time.
Char Buf [num]; // because eight 8192-sized DMA buffers are opened in the driver, each time a buffer needs to be fully written, it is sent through DMA, so that the number of cycles will be less.
Get_num = fread (BUF, file_fd); // skip the first 36 bytes of Wav file Audio Information
While (feof (file_fd) = 0)
{
Get_num = fread (BUF, 1, num, file_fd );
Write (dsp_fd, Buf, get_num );
If (get_num! = Num)
{
Close (dsp_fd );
Fclose (file_fd );
Return 0;
}
}
Close (dsp_fd );
Fclose (file_fd );
Return 0;
}
Int main ()
{
Int value;
Value = s32410_audio_play ("down.wav", 44100,2, 16 );
Fprintf (stderr, "value is % d/N", value );
Return 0;
}