OpenCores
URL https://opencores.org/ocsvn/aic1106_avalon_ip/aic1106_avalon_ip/trunk

Subversion Repositories aic1106_avalon_ip

[/] [aic1106_avalon_ip/] [trunk/] [software driver example/] [audio_drv.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 AlexO
/*
2
 * audio_drv.c
3
 *
4
 *  Created on: Jun 22, 2014
5
 *      Author: AlexO
6
 */
7
 
8
#include <stdio.h>
9
#include <string.h>
10
#include <stdlib.h>
11
#include <unistd.h>
12
#include <float.h>
13
#include <math.h>
14
#include <sys/alt_cache.h>
15
#include <sys/alt_irq.h>
16
#include <sys/time.h>
17
#include <fcntl.h>
18
#include "sys/alt_timestamp.h"
19
#include "sys/alt_alarm.h"
20
#include "altera_avalon_fifo_regs.h"
21
#include "altera_avalon_fifo_util.h"
22
#include "alt_types.h"
23
#include "altera_avalon_spi_regs.h"
24
#include "altera_avalon_spi.h"
25
#include "altera_avalon_pio_regs.h"
26
#include "altera_avalon_uart.h"
27
#include "altera_avalon_uart_regs.h"
28
#include "altera_vic_irq.h"
29
#include "altera_vic_regs.h"
30
#include "system.h"
31
 
32
#include "fifo.h"
33
#include "audio_drv.h"
34
 
35
#define DEBUG_LOG                               AUDIO_DRV_DEBUG_LOG
36
#define AUDIO_DEV_PATH                  "/mnt/audio/"
37
#define AUDIO_DRV_HANDLE                0x0000001
38
#define AUDIO_INP_FIFO_SZ               8000 //2sec
39
#define AUDIO_BEEP_BUF_DURATION_MS      10
40
 
41
#define LOG_PRINT()
42
 
43
typedef struct{
44
    char rID[4];      // 'RIFF'
45
    long int rLen;
46
    char wID[4];      // 'WAVE'
47
    char fId[4];      // 'fmt'
48
    long int pcmHeaderLength;
49
    short int wFormatTag;
50
    short int numChannels;
51
    long int nSamplesPerSec;
52
    long int nAvgBytesPerSec;
53
    short int numBlockAlingn;
54
    short int numBitsPerSample;
55
}  __attribute__ (( packed ))  WAV_HDR;
56
 
57
/* header of wave file */
58
typedef struct
59
{
60
    char dId[4];  // 'data' or 'fact'
61
    long int dLen;
62
}  __attribute__ (( packed )) CHUNK_HDR;
63
 
64
void (*g_audio_idle_fn)(alt_fd* fd)  = NULL;
65
static int g_dev_opened = 0;
66
static int g_io_cancel_req = 0;
67
static int g_cur_volume = SYS_SOUND_VOLUME;
68
static int g_inp_fifo_ovf_cnt = 0;
69
static int g_out_fifo_udf_cnt = 0;
70
static int g_out_flag = 0;
71
 
72
void* fifo_lock()
73
{
74
         return (void*)alt_irq_disable_all();
75
}
76
 
77
void fifo_unlock(void* ctx)
78
{
79
        alt_irq_enable_all((alt_irq_context)ctx);
80
}
81
 
82
MAKE_FIFO_INSTANCE(audio_inp, AUDIO_INP_FIFO_SZ, alt_u32, fifo_lock, fifo_unlock);
83
 
84
 
85
void aic1106_inp_irq_handler(void* context)
86
{
87
        alt_u32 smp2x16;
88
        volatile int fifo_evt;
89
 
90
        fifo_evt = altera_avalon_fifo_read_event(AIC1106_INPUT_FIFO_OUT_CSR_BASE, ALTERA_AVALON_FIFO_EVENT_ALL);
91
        if (fifo_evt & ALTERA_AVALON_FIFO_EVENT_OVF_MSK)
92
        {
93
                g_inp_fifo_ovf_cnt++;
94
        }
95
 
96
        while (!(IORD_ALTERA_AVALON_FIFO_STATUS(AIC1106_INPUT_FIFO_OUT_CSR_BASE) & ALTERA_AVALON_FIFO_STATUS_E_MSK))
97
        {
98
                smp2x16 = IORD_ALTERA_AVALON_FIFO_DATA(AIC1106_INPUT_FIFO_OUT_BASE);
99
 
100
 
101
#if SYSID_ID == 0xABBA002 || SYSID_ID == 0xABBA003
102
                // followed code fix HW bug in aic1106_pcm.v (aso_valid signal gated two times)
103
                // for fix it in HW lets change line 129 as followed:
104
                // wire     fs_rxvalid_off     = (main_cnt == 9'd278);
105
                // I spent 3 fucking days for found it !!!
106
                static unsigned char nsmp = 0;
107
                if (nsmp++ & 0x01)
108
                {
109
                        audio_inp_put(smp2x16);
110
                }
111
#elif SYSID_ID >= 0xABBA004
112
                // Followed code assume that HW bug fixed (since 0xABBA004)
113
                audio_inp_put(smp2x16);
114
#else
115
#error AUDIO_DRV: UNKNOWN HARDWARE VERSION
116
#endif
117
        }
118
 
119
        altera_avalon_fifo_clear_event(AIC1106_INPUT_FIFO_OUT_CSR_BASE, ALTERA_AVALON_FIFO_EVENT_ALL);
120
 
121
}
122
 
123
int audio_open(alt_fd* fd, const char* name, int flags, int mode)
124
{
125
        int ret_code = -ENOENT;
126
        int handle = 0;
127
 
128
        if (!g_dev_opened)
129
        {
130
                audio_inp_clean();
131
 
132
                IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_RESET);
133
                usleep(10);
134
 
135
                altera_avalon_fifo_clear_event(AIC1106_OUTPUT_FIFO_IN_CSR_BASE, ALTERA_AVALON_FIFO_EVENT_ALL);
136
                altera_avalon_fifo_clear_event(AIC1106_INPUT_FIFO_OUT_CSR_BASE, ALTERA_AVALON_FIFO_EVENT_ALL);
137
 
138
                // flush fifo
139
                while (!(IORD_ALTERA_AVALON_FIFO_STATUS(AIC1106_INPUT_FIFO_OUT_CSR_BASE) & ALTERA_AVALON_FIFO_STATUS_E_MSK))
140
                {
141
                        IORD_ALTERA_AVALON_FIFO_DATA(AIC1106_INPUT_FIFO_OUT_BASE);
142
                }
143
 
144
                altera_avalon_fifo_write_ienable(AIC1106_INPUT_FIFO_OUT_CSR_BASE, ALTERA_AVALON_FIFO_IENABLE_ALL);
145
 
146
                IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_ENABLE | g_cur_volume);
147
 
148
                handle = AUDIO_DRV_HANDLE;
149
                g_dev_opened = 1;
150
                g_io_cancel_req = 0;
151
                g_inp_fifo_ovf_cnt = 0;
152
                g_out_fifo_udf_cnt = 0;
153
                g_out_flag = 0;
154
                ret_code = AUDIO_SUCCESS;
155
        }
156
 
157
        fd->priv = (alt_u8*)handle;
158
 
159
        LOG_PRINT(LOG_DEBUG, ":: name=%s, audio_flags=0x%08x, mode=%d, handle=%d\n\r", name, (unsigned int)flags, mode, handle);
160
 
161
        return ret_code;
162
}
163
 
164
int audio_close(alt_fd* fd)
165
{
166
        int ret_code = -ENOENT;
167
 
168
        if ((int)fd->priv == AUDIO_DRV_HANDLE)
169
        {
170
                altera_avalon_fifo_write_ienable(AIC1106_INPUT_FIFO_OUT_CSR_BASE, 0);
171
                g_dev_opened = 0;
172
 
173
                if (g_out_fifo_udf_cnt > 0)
174
                {
175
                        LOG_PRINT(LOG_DEBUG, "::Output stream %d times underflow detected\n\r", g_out_fifo_udf_cnt);
176
                }
177
 
178
                if (g_inp_fifo_ovf_cnt > 0)
179
                {
180
                        LOG_PRINT(LOG_DEBUG, "::Input stream %d times overflow detected\n\r", g_inp_fifo_ovf_cnt);
181
                }
182
 
183
                ret_code = AUDIO_SUCCESS;
184
        }
185
 
186
        LOG_PRINT(LOG_DEBUG, "::handle=%d, ret_code=%d\n\r", (int)fd->priv, ret_code);
187
 
188
        return ret_code;
189
}
190
 
191
int audio_read(alt_fd* fd, char* ptr, int len)
192
{
193
        static int stw = 0;
194
        static alt_u32 s32;
195
        int cnt = 0;
196
        char* pptr = (char*)ptr;
197
 
198
        while (cnt < len)
199
        {
200
                if (g_io_cancel_req)
201
                {
202
                        LOG_PRINT(LOG_DEBUG, "::IO CANCELLED; len=%d, ret_code=%d\n\r", len, cnt);
203
                        break;
204
                }
205
 
206
                switch (stw)
207
                {
208
                        case 0:
209
                                while (audio_inp_empty())
210
                                {
211
                                        if (g_audio_idle_fn != NULL)
212
                                        {
213
                                                g_audio_idle_fn(fd); // up to 60 msec is still safe
214
                                        }
215
                                }
216
                                audio_inp_get(&s32);
217
 
218
                                *pptr++ = s32 & 0xff;
219
                                stw++;
220
                                break;
221
 
222
                        case 1: *pptr++ = (s32 >> 8) & 0xff;  stw++;    break;
223
                        case 2: *pptr++ = (s32 >> 16) & 0xff; stw++;    break;
224
                        case 3: *pptr++ = (s32 >> 24) & 0xff; stw = 0;   break;
225
                }
226
                cnt++;
227
        }
228
 
229
        //LOG_PRINT(LOG_DEBUG, "::handle=%d, len=%d, ret_code=%d\n\r", (int)fd->priv, len, cnt);
230
        return cnt;
231
}
232
 
233
int audio_write(alt_fd* fd, const char* ptr, int len)
234
{
235
        static alt_u8 b0, b1, b2, b3;
236
        static int stw = 0;
237
        alt_u32 s32;
238
        int cnt = 0;
239
        char* pptr = (char*)ptr;
240
 
241
        while (cnt < len)
242
        {
243
                if (g_io_cancel_req)
244
                {
245
                        LOG_PRINT(LOG_DEBUG, "::IO CANCELLED; len=%d, ret_code=%d\n\r", len, cnt);
246
                        break;
247
                }
248
 
249
                switch (stw)
250
                {
251
                        case 0: b0 = *pptr++; stw++; break;
252
                        case 1: b1 = *pptr++; stw++; break;
253
                        case 2: b2 = *pptr++; stw++; break;
254
                        case 3: b3 = *pptr++;
255
                                        stw = 0;
256
                                        s32 = ((b3 << 24) | (b2 << 16) | (b1 << 8) | b0) & 0x1fff1fff;
257
 
258
                                        if (g_out_flag && altera_avalon_fifo_read_event(AIC1106_OUTPUT_FIFO_IN_CSR_BASE, ALTERA_AVALON_FIFO_STATUS_E_MSK))
259
                                        {
260
                                                g_out_fifo_udf_cnt++;
261
                                                altera_avalon_fifo_clear_event(AIC1106_OUTPUT_FIFO_IN_CSR_BASE, ALTERA_AVALON_FIFO_EVENT_ALL);
262
                                        }
263
 
264
                                        while (IORD_ALTERA_AVALON_FIFO_STATUS(AIC1106_OUTPUT_FIFO_IN_CSR_BASE) & ALTERA_AVALON_FIFO_STATUS_F_MSK)
265
                                        {
266
                                                if (g_audio_idle_fn != NULL)
267
                                                {
268
                                                        g_audio_idle_fn(fd); // up to 60 msec is still safe
269
                                                }
270
                                        }
271
                                        IOWR_ALTERA_AVALON_FIFO_DATA(AIC1106_OUTPUT_FIFO_IN_BASE, s32);
272
                                        g_out_flag = 1;
273
 
274
                                        break;
275
                }
276
                cnt++;
277
        }
278
 
279
        //LOG_PRINT(LOG_DEBUG, "::handle=%d, len=%d, ret_code=%d\n\r", (int)fd->priv, len, cnt);
280
        return cnt;
281
}
282
 
283
int audio_ioctl(alt_fd* fd, int req, void* arg)
284
{
285
        int ret_code = -EINVAL;
286
 
287
        switch (req)
288
        {
289
        case AUDIO_IOCTL_SET_VOL:
290
                g_cur_volume = *((int*)arg) & 0x000000F;
291
                IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_ENABLE | g_cur_volume);
292
                ret_code = AUDIO_SUCCESS;
293
                break;
294
 
295
        case AUDIO_IOCTL_GET_VOL:
296
                *((int*)arg) = g_cur_volume;
297
                ret_code = AUDIO_SUCCESS;
298
                break;
299
 
300
        case AUDIO_IOCTL_RESET:
301
                IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_RESET);
302
                ret_code = AUDIO_SUCCESS;
303
                break;
304
 
305
        case AUDIO_IOCTL_LOOPBACK:
306
                IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_LOOPBACK);
307
                ret_code = AUDIO_SUCCESS;
308
                break;
309
 
310
        case AUDIO_IOCTL_IOCANCEL:
311
                g_io_cancel_req = 1;
312
                ret_code = AUDIO_SUCCESS;
313
                break;
314
 
315
        default:
316
                break;
317
        }
318
 
319
        //LOG_PRINT(LOG_DEBUG, "handle=%d, req=%d, arg=%d, ret_code=%d\n\r", (int)fd->priv, req, *((int*)arg), ret_code);
320
        return ret_code;
321
}
322
 
323
 
324
int audio_io_cancel()
325
{
326
        g_io_cancel_req = 1;
327
        return AUDIO_SUCCESS;
328
        //return ioctl(0, AUDIO_IOCTL_IOCANCEL, NULL);
329
}
330
 
331
void audio_set_idle_callback(void (*idle_fn)(alt_fd* fd))
332
{
333
        g_audio_idle_fn = idle_fn;
334
}
335
 
336
int audio_write_direct(char* ptr, int len)
337
{
338
        int rval;
339
 
340
        if (!g_dev_opened)
341
        {
342
                audio_inp_clean();
343
 
344
                IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_RESET);
345
                usleep(10);
346
 
347
                altera_avalon_fifo_clear_event(AIC1106_OUTPUT_FIFO_IN_CSR_BASE, ALTERA_AVALON_FIFO_EVENT_ALL);
348
                altera_avalon_fifo_clear_event(AIC1106_INPUT_FIFO_OUT_CSR_BASE, ALTERA_AVALON_FIFO_EVENT_ALL);
349
 
350
                // flush fifo
351
                while (!(IORD_ALTERA_AVALON_FIFO_STATUS(AIC1106_INPUT_FIFO_OUT_CSR_BASE) & ALTERA_AVALON_FIFO_STATUS_E_MSK))
352
                {
353
                        IORD_ALTERA_AVALON_FIFO_DATA(AIC1106_INPUT_FIFO_OUT_BASE);
354
                }
355
 
356
                altera_avalon_fifo_write_ienable(AIC1106_INPUT_FIFO_OUT_CSR_BASE, ALTERA_AVALON_FIFO_IENABLE_ALL);
357
 
358
                IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_ENABLE | g_cur_volume);
359
 
360
                g_dev_opened = 1;
361
                g_io_cancel_req = 0;
362
                g_inp_fifo_ovf_cnt = 0;
363
                g_out_fifo_udf_cnt = 0;
364
                g_out_flag = 0;
365
        }
366
 
367
        rval = audio_write(NULL, ptr, len);
368
 
369
        altera_avalon_fifo_write_ienable(AIC1106_INPUT_FIFO_OUT_CSR_BASE, 0);
370
        g_dev_opened = 0;
371
 
372
        if (g_out_fifo_udf_cnt > 0)
373
        {
374
                LOG_PRINT(LOG_DEBUG, "::Output stream %d times underflow detected\n\r", g_out_fifo_udf_cnt);
375
        }
376
 
377
        if (g_inp_fifo_ovf_cnt > 0)
378
        {
379
                LOG_PRINT(LOG_DEBUG, "::Input stream %d times overflow detected\n\r", g_inp_fifo_ovf_cnt);
380
        }
381
 
382
        return rval;
383
}
384
 
385
int audio_driver_init()
386
{
387
        static int g_already_initialized = FALSE;
388
        static alt_dev g_audio_dev =
389
          {
390
            ALT_LLIST_ENTRY,
391
            AUDIO_DEV_PATH,
392
            audio_open,
393
            audio_close,
394
            audio_read,
395
            audio_write,
396
            NULL,
397
            NULL,
398
            audio_ioctl
399
          };
400
 
401
        int ret_code = AUDIO_FAIL;
402
 
403
        IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_RESET);
404
        altera_avalon_fifo_init(AIC1106_OUTPUT_FIFO_IN_CSR_BASE,        0,       AIC1106_ALMOST_EMPTY,   AIC1106_ALMOST_FULL);
405
        altera_avalon_fifo_init(AIC1106_INPUT_FIFO_OUT_CSR_BASE,        0,       AIC1106_ALMOST_EMPTY,   AIC1106_ALMOST_FULL);
406
 
407
        if (g_already_initialized)
408
        {
409
                return AUDIO_SUCCESS;
410
        }
411
 
412
        ret_code = alt_ic_isr_register(VIC_INTERRUPT_CONTROLLER_ID, AIC1106_INPUT_FIFO_OUT_CSR_IRQ, aic1106_inp_irq_handler, NULL, NULL);
413
        if (ret_code != 0)
414
        {
415
                goto _EXIT;
416
        }
417
 
418
        ret_code = alt_fs_reg(&g_audio_dev);
419
        if (ret_code != 0)
420
        {
421
                // unregister IRQ handler
422
                alt_ic_isr_register(VIC_INTERRUPT_CONTROLLER_ID, AIC1106_INPUT_FIFO_OUT_CSR_IRQ, NULL, NULL, NULL);
423
        }
424
 
425
_EXIT:
426
 
427
        if (ret_code == AUDIO_SUCCESS)
428
        {
429
                g_already_initialized = TRUE;
430
        }
431
 
432
        return ret_code;
433
}
434
 
435
void    audio_set_volume(int volume)
436
{
437
        g_cur_volume = volume & 0x000000F;
438
        IOWR_ALTERA_AVALON_PIO_DATA(AIC1106_BASE, AIC1106_ENABLE | g_cur_volume);
439
}
440
 
441
int             audio_get_volume()
442
{
443
        return g_cur_volume;
444
}
445
 
446
int audio_beep(int volume, int freq, int duration_ms, int pause_ms, int beep_count)
447
{
448
        int ret_val = AUDIO_FAIL;
449
        //int audio_fd;
450
        int ix, np;
451
        alt_16 wav_buf[AUDIO_BEEP_BUF_DURATION_MS * (AIC1106_SAMPLE_RATE / 1000)]; // allocate buffer for AUDIO_BEEP_BUF_DURATION_MS
452
        float t;
453
 
454
        if (freq < (1.0 / (AUDIO_BEEP_BUF_DURATION_MS / 1000.0)))
455
        {
456
                freq = (1.0 / (AUDIO_BEEP_BUF_DURATION_MS / 1000.0));
457
        }
458
 
459
        if (duration_ms < 20)
460
        {
461
                duration_ms = 20;
462
        }
463
 
464
        if (pause_ms < 50)
465
        {
466
                pause_ms = 50;
467
        }
468
 
469
        np = sizeof(wav_buf) / sizeof(alt_16); //AIC1106_SAMPLE_RATE / freq;
470
 
471
        // generate AUDIO_BEEP_BUF_DURATION_MS of signal
472
        t = 0;
473
        for (ix = 0; ix < np; ix++)
474
        {
475
                wav_buf[ix] = floor(4095.0 * sin(2 * 3.1415926 * freq * t));
476
                t += 1.0 / AIC1106_SAMPLE_RATE;
477
        }
478
 
479
                audio_set_volume(volume);
480
 
481
                for (ix = 0; ix < beep_count; ix++)
482
                {
483
                        //audio_fd = open("/mnt/audio/", O_WRONLY);
484
                        //if (audio_fd <= 0) goto _EXIT;
485
 
486
                        t = 0;
487
                        while (t < duration_ms)
488
                        {
489
                                //write(audio_fd, wav_buf, sizeof(wav_buf));
490
                                audio_write_direct(wav_buf, sizeof(wav_buf));
491
                                t += 1000.0 * np / AIC1106_SAMPLE_RATE;
492
                                if (g_io_cancel_req)
493
                                {
494
                                        //close(audio_fd);
495
                                        goto _EXIT;
496
                                }
497
                        }
498
 
499
                        //close(audio_fd);
500
 
501
                        alt_u32 stop_tick = pause_ms / 1000.0 * alt_ticks_per_second() + alt_nticks();
502
                        while (alt_nticks() < stop_tick)
503
                        {
504
                                if (g_audio_idle_fn != NULL)
505
                                {
506
                                        g_audio_idle_fn(NULL);
507
                                        if (g_io_cancel_req) goto _EXIT;
508
                                }
509
                        }
510
                }
511
                ret_val = AUDIO_SUCCESS;
512
 
513
_EXIT:
514
 
515
        return ret_val;
516
}
517
 
518
alt_16* audio_read_wav(char* fname, int* samples_num)
519
{
520
    alt_16* pWavData;
521
    long int maxInSamples;
522
 
523
    int i;
524
    FILE *pFile;
525
    unsigned int stat;
526
    char outBuffer[80];
527
 
528
    WAV_HDR   WavHeader;
529
    CHUNK_HDR ChunkHeader;
530
 
531
    short int* pU;
532
    int sFlag;
533
    long int rMore;
534
 
535
    char* wBuffer;
536
    int wBufferLength;
537
 
538
    /* set the defaults values. */
539
    pWavData = NULL;
540
    wBuffer = NULL;
541
    maxInSamples = 0;
542
    pFile = NULL;
543
 
544
    /*
545
     * open the wav file
546
     */
547
    pFile = fopen( fname, "rb");
548
    if(pFile == NULL)
549
    {
550
        LOG_PRINT(LOG_ERROR, "::Can't open wav file.\n\r");
551
        goto _EXIT;
552
    }
553
 
554
    /* read riff/wav header */
555
    stat = fread((void*) &WavHeader, sizeof(WAV_HDR), (size_t)1, pFile);
556
    if(stat != 1)
557
    {
558
        LOG_PRINT(LOG_ERROR, "::Header missing. May be format is not OK!\n\r");
559
        goto _EXIT;
560
    }
561
 
562
    /* check format of header */
563
    for(i = 0; i < 4; i++)
564
    {
565
        outBuffer[i] = WavHeader.rID[i];
566
    }
567
    outBuffer[4] = 0;
568
    if(strcmp(outBuffer, "RIFF") != 0)
569
    {
570
        LOG_PRINT(LOG_ERROR, "::Bad RIFF format.\n\r");
571
        goto _EXIT;
572
    }
573
 
574
    for(i = 0; i < 4; i++)
575
    {
576
        outBuffer[i] = WavHeader.wID[i];
577
    }
578
    outBuffer[4] = 0;
579
 
580
    if(strcmp(outBuffer, "WAVE") != 0)
581
    {
582
        LOG_PRINT(LOG_ERROR, "::Bad WAVE format\n\r");
583
        goto _EXIT;
584
    }
585
 
586
    for(i = 0; i < 4; i++)
587
    {
588
        outBuffer[i] = WavHeader.fId[i];
589
    }
590
    outBuffer[4] = 0;
591
 
592
    if(strcmp(outBuffer, "fmt ") != 0) // not with "fmt" since 4th pos is blank
593
    {
594
        LOG_PRINT(LOG_ERROR, "::Bad fmt format\n\r");
595
        goto _EXIT;
596
    }
597
 
598
    if(WavHeader.wFormatTag != 1)
599
    {
600
        LOG_PRINT(LOG_ERROR, "::Bad wav wFormatTag\n\r");
601
        goto _EXIT;
602
    }
603
 
604
    /*
605
     * Skip over any remaining portion of wav header.
606
     */
607
    rMore = WavHeader.pcmHeaderLength - (sizeof(WAV_HDR) - 20);
608
    if( 0 != fseek(pFile, rMore, SEEK_CUR))
609
    {
610
        LOG_PRINT(LOG_ERROR, "::Can't seek.\n\r");
611
    }
612
 
613
    /*
614
     * read chunk untill a data chunk is found.
615
     */
616
 
617
    sFlag = 1;
618
    while(sFlag != 0)
619
    {
620
        // check attempts.
621
        if(sFlag > 10)
622
        {
623
                LOG_PRINT(LOG_ERROR, "::Too many chunks\n\r");
624
            goto _EXIT;
625
        }
626
 
627
        // read chunk header
628
        stat = fread((void*)&ChunkHeader, sizeof(CHUNK_HDR), (size_t)1, pFile);
629
        if( 1 != stat)
630
        {
631
            LOG_PRINT(LOG_ERROR, "::Can't read data.\n\r");
632
            goto _EXIT;
633
        }
634
 
635
        // check chunk type.
636
        for(i =0; i < 4; i++)
637
        {
638
            outBuffer[i] = ChunkHeader.dId[i];
639
        }
640
        outBuffer[4] = 0;
641
        if(strcmp(outBuffer, "data") == 0) { break;}
642
 
643
        // skip over chunk.
644
        sFlag++;
645
        stat = fseek(pFile, ChunkHeader.dLen, SEEK_CUR);
646
        if(stat != 0)
647
        {
648
            LOG_PRINT(LOG_ERROR, "::Can't seek.\n\r");
649
            goto _EXIT;
650
        }
651
 
652
    }
653
 
654
    if (WavHeader.nSamplesPerSec != 8000)
655
    {
656
        LOG_PRINT(LOG_ERROR, "::Only 8000Hz sample rate is supported.\n\r");
657
        goto _EXIT;
658
    }
659
 
660
    if(WavHeader.numBitsPerSample != 16)
661
    {
662
        LOG_PRINT(LOG_ERROR, "::Only 16 bit sample is supported.\n\r");
663
        goto _EXIT;
664
    }
665
 
666
    if(WavHeader.numChannels != 1)
667
    {
668
        LOG_PRINT(LOG_ERROR, "::Only 1 channel is supported.\n\r");
669
        goto _EXIT;
670
    }
671
 
672
    /* find length of remaining data. */
673
    wBufferLength = ChunkHeader.dLen;
674
 
675
    /* find number of samples. */
676
    maxInSamples = ChunkHeader.dLen;
677
    maxInSamples /= WavHeader.numBitsPerSample/8;
678
 
679
 
680
    /* allocate new buffers */
681
    wBuffer = malloc(wBufferLength);
682
    if( wBuffer == NULL)
683
    {
684
        LOG_PRINT(LOG_ERROR, "::Can't allocate wBuffer.\n\r");
685
        goto _EXIT;
686
    }
687
 
688
    pWavData = malloc(maxInSamples*sizeof(alt_16));
689
    if(pWavData == NULL)
690
    {
691
        LOG_PRINT(LOG_ERROR, "::Can't allocate pWavData\n\r");
692
        goto _EXIT;
693
    }
694
 
695
    /* read signal data */
696
 
697
    stat = fread((void*)wBuffer, wBufferLength, (size_t)1, pFile);
698
    if( 1 != stat)
699
    {
700
        LOG_PRINT(LOG_ERROR, "::Can't read buffer.\n\r");
701
        free(pWavData);
702
        pWavData = NULL;
703
        goto _EXIT;
704
    }
705
 
706
    /* convert data to  13 bit linear format for AIC1106 codec*/
707
    pU = (alt_16*) wBuffer;
708
    for( i = 0; i < maxInSamples; i++)
709
    {
710
        pWavData[i] = pU[i] / 8;
711
    }
712
 
713
_EXIT:
714
 
715
  /* reset and delete */
716
   if(wBuffer != NULL)
717
           free(wBuffer);
718
 
719
   fclose(pFile);
720
 
721
   *samples_num = maxInSamples;
722
 
723
   return pWavData;
724
}
725
 
726
int audio_write_wav_header(FILE *fw, int samples_num)
727
{
728
        unsigned int wstat;
729
        int i;
730
        char* obuff;
731
 
732
        WAV_HDR wav;
733
        CHUNK_HDR chk;
734
 
735
        int num_ch = 1;
736
 
737
        // setup wav header
738
        obuff = "RIFF";
739
        for (i = 0; i < 4; i++)
740
                wav.rID[i] = obuff[i];
741
 
742
        obuff = "WAVE";
743
        for (i = 0; i < 4; i++)
744
                wav.wID[i] = obuff[i];
745
 
746
        obuff = "fmt ";
747
        for (i = 0; i < 4; i++)
748
                wav.fId[i] = obuff[i];
749
 
750
        // setup chunk header
751
        obuff = "data";
752
        for (i = 0; i < 4; i++)
753
        {
754
                chk.dId[i] = obuff[i];
755
        }
756
 
757
        wav.numBitsPerSample = AIC1106_BITS_PER_SAMPLE;
758
        wav.nSamplesPerSec = AIC1106_SAMPLE_RATE;
759
        wav.nAvgBytesPerSec = AIC1106_SAMPLE_RATE * (AIC1106_BITS_PER_SAMPLE / 8) * num_ch;
760
        wav.numChannels = num_ch;
761
 
762
        wav.pcmHeaderLength = 16;
763
        wav.wFormatTag = 1;
764
        wav.rLen = sizeof(WAV_HDR) + sizeof(CHUNK_HDR) + samples_num*sizeof(alt_16);
765
        wav.numBlockAlingn = num_ch * AIC1106_BITS_PER_SAMPLE / 8;
766
 
767
        chk.dLen = samples_num*sizeof(alt_16);
768
 
769
        /* rewind file to beginning */
770
        fseek(fw, 0, SEEK_SET);
771
 
772
        /* write riff/wav header */
773
        wstat = fwrite((void *)&wav, sizeof(WAV_HDR), (size_t) 1, fw);
774
        if (wstat != 1)
775
        {
776
                LOG_PRINT(LOG_ERROR, "::Can't write wav header\n\r");
777
                return -2;
778
        }
779
 
780
        /* write chunk header */
781
        wstat = fwrite((void *)&chk, sizeof(CHUNK_HDR), (size_t) 1, fw);
782
        if (wstat != 1)
783
        {
784
                LOG_PRINT(LOG_ERROR, "::Can't write chk header\n\r");
785
                return -3;
786
        }
787
 
788
        return sizeof(WAV_HDR) + sizeof(CHUNK_HDR);
789
}
790
 
791
int audio_write_wav(char* fname, alt_16 *sample_ptr, int samples_num)
792
{
793
        FILE *fw;
794
        unsigned int wstat;
795
 
796
        /* open wav file */
797
        fw = fopen(fname, "wb");
798
        if (fw == NULL)
799
        {
800
                printf("Can't open wav file\n\r");
801
                return AUDIO_FAIL;
802
        }
803
 
804
        if (audio_write_wav_header(fw, samples_num) > 0)
805
        {
806
                /* write data */
807
                wstat = fwrite((void *) sample_ptr, samples_num * sizeof(alt_16), (size_t) 1, fw);
808
                if (wstat != 1)
809
                {
810
                        LOG_PRINT(LOG_ERROR, "::Can't write wave data\n\r");
811
                        return AUDIO_FAIL;
812
                }
813
        }
814
        fclose(fw);
815
 
816
        return samples_num;
817
}
818
 
819
int     audio_play_wav(char* fname)
820
{
821
        alt_16*         buffer = NULL;
822
        int             samples_num;
823
        int             audio_fd;
824
        int                     ret_val = AUDIO_FAIL;
825
 
826
        buffer = audio_read_wav(fname, &samples_num);
827
 
828
        if ((samples_num > 0) && (buffer != NULL))
829
        {
830
                audio_fd = open("/mnt/audio/", O_RDWR);
831
 
832
                if (audio_fd > 0)
833
                {
834
                        write(audio_fd, buffer, samples_num * sizeof(alt_16));
835
                        close(audio_fd);
836
                        ret_val = AUDIO_SUCCESS;
837
                }
838
        }
839
 
840
        if (buffer != NULL)
841
        {
842
                free(buffer);
843
        }
844
 
845
        return ret_val;
846
}
847
 
848
#define AUDIO_CHUNK_SIZE        100 /*msec*/
849
int     audio_record_wav(char* fname, int (*rec_callback)(int time))
850
{
851
        FILE*   wav_file;
852
        FILE*   audio_dev;
853
        int     samples_num;
854
        int             chunk_size;
855
        int             wstat;
856
        int     ret_val = AUDIO_FAIL;
857
        char*   audio_chunk;
858
 
859
        /* open wav file */
860
    wav_file = fopen(fname, "wb");
861
        if (wav_file == NULL)
862
        {
863
                LOG_PRINT(LOG_ERROR, "::Can't open wave file.\n\r");
864
                return ret_val;
865
        }
866
 
867
        if (audio_write_wav_header(wav_file, 0) == 0)
868
        {
869
                LOG_PRINT(LOG_ERROR, "::Can't write header to wave file.\n\r");
870
                return ret_val;
871
        }
872
 
873
        chunk_size = AUDIO_CHUNK_SIZE * AIC1106_SAMPLE_RATE / 1000 * sizeof(alt_16);
874
        audio_chunk = malloc(chunk_size);
875
    if(audio_chunk == NULL)
876
    {
877
        LOG_PRINT(LOG_ERROR, "::Can't allocate audio_buf.\n\r");
878
        return ret_val;
879
    }
880
 
881
        audio_dev = fopen("/mnt/audio/", "r");
882
        samples_num = 0;
883
 
884
        while (1)
885
        {
886
                if (rec_callback(1000 * samples_num / AIC1106_SAMPLE_RATE))
887
                {
888
                        if (audio_write_wav_header(wav_file, samples_num) > 0)
889
                        {
890
                                ret_val = samples_num;
891
                        }
892
                        break;
893
                }
894
 
895
                if ((wstat=fread((void*)audio_chunk, 1, chunk_size, audio_dev)) == chunk_size)
896
                {
897
                        if ((wstat=fwrite((void*)audio_chunk, 1, chunk_size, wav_file)) == chunk_size)
898
                        {
899
                                samples_num += chunk_size / sizeof(alt_16);
900
                        }
901
                        else
902
                        {
903
                                LOG_PRINT(LOG_ERROR, "::Can't write wave data to file (%d).\n\r", wstat);
904
                                break;
905
                        }
906
                }
907
                else
908
                {
909
                        LOG_PRINT(LOG_ERROR, "::Can't read wave data from device (%d).\n\r", wstat);
910
                        break;
911
                }
912
        }
913
 
914
        fclose(audio_dev);
915
        fclose(wav_file);
916
        free(audio_chunk);
917
 
918
        return ret_val;
919
}
920
 
921
int             PlayWavFile(char* fname, int volume)
922
{
923
        audio_set_volume(volume);
924
        return audio_play_wav(fname);
925
}
926
 
927
void    SoundToneAlarm(int volume, int freq, int duration_ms, int pause_ms, int beep_count)
928
{
929
        audio_beep(volume, freq, duration_ms, pause_ms, beep_count);
930
}
931
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.