aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/ecore_audio/ecore_audio_obj_in_tone.c
blob: 2b097f66f10d4e17ee0d848760432d49a7cf9eb2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef HAVE_FEATURES_H
#include <features.h>
#endif

#include <Eo.h>
#include "ecore_audio_private.h"
#include <math.h>

#define MY_CLASS ECORE_AUDIO_IN_TONE_CLASS
#define MY_CLASS_NAME "Ecore_Audio_In_Tone"

struct _Ecore_Audio_In_Tone_Data
{
  int freq;
  int phase;
};

typedef struct _Ecore_Audio_In_Tone_Data Ecore_Audio_In_Tone_Data;

EOLIAN static ssize_t
_ecore_audio_in_tone_ecore_audio_in_read_internal(Eo *eo_obj, Ecore_Audio_In_Tone_Data *obj, void *data, size_t len)
{
  size_t i, remain;
  Ecore_Audio_Input *in_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);

  float *val = data;

  remain = in_obj->length * in_obj->samplerate * 4 - obj->phase * 4;
  if (remain > len)
    remain = len;

  for (i=0; i<remain/4; i++) {
      val[i] = sin(2* M_PI * obj->freq * (obj->phase + i) / in_obj->samplerate);
  }

  obj->phase += i;

  return remain;
}

EOLIAN static double
_ecore_audio_in_tone_ecore_audio_in_seek(Eo *eo_obj, Ecore_Audio_In_Tone_Data *obj, double offs, int mode)
{
  int tmp;
  Ecore_Audio_Input *in_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);

  switch (mode) {
    case SEEK_SET:
      tmp = offs * in_obj->samplerate;
      break;
    case SEEK_CUR:
      tmp = obj->phase + offs * in_obj->samplerate;
      break;
    case SEEK_END:
      tmp = (in_obj->length + offs) * in_obj->samplerate;
      break;
    default:
      goto err;
  }
  if ((tmp < 0) || (tmp > in_obj->length * in_obj->samplerate))
    goto err;

  obj->phase = tmp;

  return (double)obj->phase / in_obj->samplerate;
err:
  return -1.0;
}

EOLIAN static void
_ecore_audio_in_tone_ecore_audio_in_length_set(Eo *eo_obj, Ecore_Audio_In_Tone_Data *_pd EINA_UNUSED, double length)
{
  Ecore_Audio_Input *in_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);
  in_obj->length = length;
}

EOLIAN static void
_ecore_audio_in_tone_eo_base_key_data_set(Eo *eo_obj, Ecore_Audio_In_Tone_Data *obj, const char *key, const void *val)
{
  if (!key) return;

  if (!strcmp(key, ECORE_AUDIO_ATTR_TONE_FREQ)) {
      obj->freq = *(int *)val;
  } else {
      eo_do_super(eo_obj, MY_CLASS, eo_key_data_set(key, val));
  }

}

EOLIAN static void*
_ecore_audio_in_tone_eo_base_key_data_get(Eo *eo_obj, Ecore_Audio_In_Tone_Data *obj, const char *key)
{
  if (!strcmp(key, ECORE_AUDIO_ATTR_TONE_FREQ)) {
      return (void *) (intptr_t) obj->freq;
  } else {
      void *ret = NULL;
      eo_do_super(eo_obj, MY_CLASS, ret = eo_key_data_get(key));
      return ret;
  }
}

EOLIAN static Eo *
_ecore_audio_in_tone_eo_base_constructor(Eo *eo_obj, Ecore_Audio_In_Tone_Data *obj)
{
  Ecore_Audio_Input *in_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);

  eo_obj = eo_do_super_ret(eo_obj, MY_CLASS, eo_obj, eo_constructor());

  in_obj->channels = 1;
  in_obj->samplerate = 44100;
  in_obj->length = 1;
  in_obj->seekable = EINA_TRUE;

  obj->freq = 1000;

  return eo_obj;
}

#include "ecore_audio_in_tone.eo.c"