1b815c7f3Sopenharmony_ci
2b815c7f3Sopenharmony_ci#include "sfconfig.h"
3b815c7f3Sopenharmony_ci
4b815c7f3Sopenharmony_ci#include <stdio.h>
5b815c7f3Sopenharmony_ci#include <stdlib.h>
6b815c7f3Sopenharmony_ci#include <math.h>
7b815c7f3Sopenharmony_ci#include <sndfile.h>
8b815c7f3Sopenharmony_ci
9b815c7f3Sopenharmony_ci
10b815c7f3Sopenharmony_cistatic void *
11b815c7f3Sopenharmony_ciget_cues (const char *filename, double *sr)
12b815c7f3Sopenharmony_ci{
13b815c7f3Sopenharmony_ci    SNDFILE    *file;
14b815c7f3Sopenharmony_ci    SF_INFO	sfinfo;
15b815c7f3Sopenharmony_ci
16b815c7f3Sopenharmony_ci    unsigned int err, size;
17b815c7f3Sopenharmony_ci    uint32_t count = 0;
18b815c7f3Sopenharmony_ci    SF_CUES_VAR(0) *info;
19b815c7f3Sopenharmony_ci
20b815c7f3Sopenharmony_ci    if ((file = sf_open(filename, SFM_READ, &sfinfo)) == NULL)
21b815c7f3Sopenharmony_ci    {
22b815c7f3Sopenharmony_ci	printf("can't open file '%s'\n", filename);
23b815c7f3Sopenharmony_ci	exit(1);
24b815c7f3Sopenharmony_ci    }
25b815c7f3Sopenharmony_ci
26b815c7f3Sopenharmony_ci    printf("\n---- get cues of file '%s'\n", filename);
27b815c7f3Sopenharmony_ci
28b815c7f3Sopenharmony_ci    if ((err = sf_command(file, SFC_GET_CUE_COUNT, &count, sizeof(uint32_t))) == SF_FALSE)
29b815c7f3Sopenharmony_ci    {
30b815c7f3Sopenharmony_ci	if (sf_error(file))
31b815c7f3Sopenharmony_ci	{
32b815c7f3Sopenharmony_ci	    printf("can't get cue info size for file '%s' (arg size %lu), err %s\n",
33b815c7f3Sopenharmony_ci		   filename, sizeof(uint32_t), sf_strerror(file));
34b815c7f3Sopenharmony_ci	    exit(2);
35b815c7f3Sopenharmony_ci	}
36b815c7f3Sopenharmony_ci	else
37b815c7f3Sopenharmony_ci	    printf("no cue info for file '%s'\n", filename);
38b815c7f3Sopenharmony_ci	return NULL;
39b815c7f3Sopenharmony_ci    }
40b815c7f3Sopenharmony_ci
41b815c7f3Sopenharmony_ci    size = sizeof(*info) + count * sizeof(SF_CUE_POINT);
42b815c7f3Sopenharmony_ci    printf("number of cues %d  size %d\n", count, size);
43b815c7f3Sopenharmony_ci
44b815c7f3Sopenharmony_ci    if (!(info = malloc(size)))
45b815c7f3Sopenharmony_ci	return NULL;
46b815c7f3Sopenharmony_ci
47b815c7f3Sopenharmony_ci    if (sf_command(file, SFC_GET_CUE, info, size) == SF_FALSE)
48b815c7f3Sopenharmony_ci    {
49b815c7f3Sopenharmony_ci	printf("can't get cue info of size %d for file '%s' error %s\n",
50b815c7f3Sopenharmony_ci	       size, filename, sf_strerror(file));
51b815c7f3Sopenharmony_ci	exit(3);
52b815c7f3Sopenharmony_ci    }
53b815c7f3Sopenharmony_ci
54b815c7f3Sopenharmony_ci    *sr = sfinfo.samplerate;
55b815c7f3Sopenharmony_ci    sf_close(file);
56b815c7f3Sopenharmony_ci
57b815c7f3Sopenharmony_ci    return info;
58b815c7f3Sopenharmony_ci}
59b815c7f3Sopenharmony_ci
60b815c7f3Sopenharmony_ci
61b815c7f3Sopenharmony_cistatic void
62b815c7f3Sopenharmony_citest_cues (const char *filename)
63b815c7f3Sopenharmony_ci{
64b815c7f3Sopenharmony_ci    unsigned int i;
65b815c7f3Sopenharmony_ci    double sr;
66b815c7f3Sopenharmony_ci    SF_CUES_VAR(0) *info = get_cues(filename, &sr);
67b815c7f3Sopenharmony_ci
68b815c7f3Sopenharmony_ci    if (info == NULL)
69b815c7f3Sopenharmony_ci	exit(1);
70b815c7f3Sopenharmony_ci
71b815c7f3Sopenharmony_ci    for (i = 0; i < info->cue_count; i++)
72b815c7f3Sopenharmony_ci    {
73b815c7f3Sopenharmony_ci	int    pos = info->cue_points[i].position;
74b815c7f3Sopenharmony_ci	double t   = (double) pos / sr;
75b815c7f3Sopenharmony_ci	double expected = i < 8  ?  (double) i / 3.  :  10. / 3.;
76b815c7f3Sopenharmony_ci	double error = (double) fabs(t - expected);
77b815c7f3Sopenharmony_ci
78b815c7f3Sopenharmony_ci	printf("cue %02d: markerID %02d  position %6d  offset %6d (time %.3f  expected %.3f  diff %f)  label '%s'\n",
79b815c7f3Sopenharmony_ci	       i, info->cue_points[i].indx, pos, info->cue_points[i].sample_offset, t, expected, error, info->cue_points[i].name);
80b815c7f3Sopenharmony_ci
81b815c7f3Sopenharmony_ci	if (error > 0.025)
82b815c7f3Sopenharmony_ci	    exit(4);
83b815c7f3Sopenharmony_ci    }
84b815c7f3Sopenharmony_ci
85b815c7f3Sopenharmony_ci    free(info);
86b815c7f3Sopenharmony_ci}
87b815c7f3Sopenharmony_ci
88b815c7f3Sopenharmony_cistatic void
89b815c7f3Sopenharmony_ciprint_cues (const char *filename)
90b815c7f3Sopenharmony_ci{
91b815c7f3Sopenharmony_ci    unsigned int i;
92b815c7f3Sopenharmony_ci    double sr;
93b815c7f3Sopenharmony_ci    SF_CUES_VAR(0) *info = get_cues(filename, &sr);
94b815c7f3Sopenharmony_ci
95b815c7f3Sopenharmony_ci    if (info == NULL)
96b815c7f3Sopenharmony_ci	exit(1);
97b815c7f3Sopenharmony_ci
98b815c7f3Sopenharmony_ci    for (i = 0; i < info->cue_count; i++)
99b815c7f3Sopenharmony_ci    {
100b815c7f3Sopenharmony_ci	int    pos    = info->cue_points[i].position;
101b815c7f3Sopenharmony_ci	int    indx   = info->cue_points[i].indx;
102b815c7f3Sopenharmony_ci	int    cstart = info->cue_points[i].chunk_start;
103b815c7f3Sopenharmony_ci	int    bstart = info->cue_points[i].block_start;
104b815c7f3Sopenharmony_ci	int    offset = info->cue_points[i].sample_offset;
105b815c7f3Sopenharmony_ci	const char *name = info->cue_points[i].name;
106b815c7f3Sopenharmony_ci	double t   = (double) pos / sr;
107b815c7f3Sopenharmony_ci
108b815c7f3Sopenharmony_ci	if (cstart != 0  ||  bstart != 0)
109b815c7f3Sopenharmony_ci	    printf("cue %02d time %7.3f: markerID %02d  position %8d  chunk_start %d  block_start %d  offset %8d  label '%s'\n",
110b815c7f3Sopenharmony_ci		   i, t, indx, pos, offset, cstart, bstart, name);
111b815c7f3Sopenharmony_ci	else
112b815c7f3Sopenharmony_ci	    printf("cue %02d  time %7.3f: markerID %02d  position %8d  offset %8d  label '%s'\n",
113b815c7f3Sopenharmony_ci		   i, t, indx, pos, offset, name);
114b815c7f3Sopenharmony_ci    }
115b815c7f3Sopenharmony_ci
116b815c7f3Sopenharmony_ci    free(info);
117b815c7f3Sopenharmony_ci}
118b815c7f3Sopenharmony_ci
119b815c7f3Sopenharmony_ci
120b815c7f3Sopenharmony_ciint
121b815c7f3Sopenharmony_cimain (int argc, char **argv)
122b815c7f3Sopenharmony_ci{
123b815c7f3Sopenharmony_ci    int i;
124b815c7f3Sopenharmony_ci
125b815c7f3Sopenharmony_ci    if (argc > 1)
126b815c7f3Sopenharmony_ci	for (i = 1; i < argc; i++)
127b815c7f3Sopenharmony_ci	    print_cues(argv[i]);
128b815c7f3Sopenharmony_ci    else
129b815c7f3Sopenharmony_ci    {
130b815c7f3Sopenharmony_ci	test_cues("clickpluck24.wav");
131b815c7f3Sopenharmony_ci	test_cues("clickpluck.wav");
132b815c7f3Sopenharmony_ci	test_cues("clickpluck.aiff");
133b815c7f3Sopenharmony_ci    }
134b815c7f3Sopenharmony_ci    return 0;
135b815c7f3Sopenharmony_ci}
136