Changeset 5624:ec1593cc8525 in roaraudio


Ignore:
Timestamp:
08/18/12 02:04:07 (12 years ago)
Author:
phi
Branch:
default
Phase:
public
Message:

Added support for RePlayGain? (RPG) control (See: #300)

Files:
12 edited

Legend:

Unmodified
Added
Removed
  • ChangeLog

    r5623 r5624  
    77        * Added meta generes (See: #301) 
    88        * Fixed metadata handling in meta.c. 
     9        * Added support for RePlayGain (RPG) control (See: #300) 
    910 
    1011v. 1.0beta4 - Mon Aug 06 2012 16:43 CEST 
  • include/libroar/stream.h

    r5535 r5624  
    5757}; 
    5858 
     59struct roar_stream_rpg { 
     60 int        mode; 
     61 uint16_t   mul; 
     62 uint16_t   div; 
     63}; 
     64 
    5965int roar_stream_connect (struct roar_connection * con, struct roar_stream * s, int dir, int mixer) _LIBROAR_STREAM_STDATTRS; 
    6066 
     
    95101int roar_stream_set_role  (struct roar_connection * con, struct roar_stream * s, int role) _LIBROAR_STREAM_STDATTRS; 
    96102 
     103int roar_stream_get_rpg   (struct roar_connection * con, struct roar_stream * s, struct roar_stream_rpg * rpg) _LIBROAR_STREAM_STDATTRS; 
     104int roar_stream_set_rpg   (struct roar_connection * con, struct roar_stream * s, const struct roar_stream_rpg * rpg) _LIBROAR_STREAM_STDATTRS; 
     105 
    97106int roar_stream_s2m     (struct roar_stream * s, struct roar_message * m); 
    98107int roar_stream_m2s     (struct roar_stream * s, struct roar_message * m); 
     
    113122const char * roar_role2str  (const int    role) _LIBROAR_ATTR_USE_RESULT _LIBROAR_ATTR_PURE; 
    114123 
     124const char * roar_rpgmode2str(const int rpgmode) _LIBROAR_ATTR_USE_RESULT _LIBROAR_ATTR_PURE; 
     125 
    115126ssize_t roar_info2samplesize (struct roar_audio_info * info) _LIBROAR_STREAM_STDATTRS _LIBROAR_ATTR_PURE; 
    116127ssize_t roar_info2framesize  (struct roar_audio_info * info) _LIBROAR_STREAM_STDATTRS _LIBROAR_ATTR_PURE; 
  • include/roaraudio/proto.h

    r5464 r5624  
    168168#define ROAR_STREAM_PARA_USAGE     10 /* used by RAUM */ 
    169169#define ROAR_STREAM_PARA_RADIO     11 /* used by RDTCS */ 
     170#define ROAR_STREAM_PARA_RPG       12 
     171 
     172// modes for ROAR_STREAM_PARA_RPG: 
     173#define ROAR_RPGMODE_DEFAULT       -1 
     174#define ROAR_RPGMODE_NONE           0 
     175#define ROAR_RPGMODE_USER           1 
     176#define ROAR_RPGMODE_ALBUM          2 
     177#define ROAR_RPGMODE_TRACK          3 
     178#define ROAR_RPGMODE_ALBUMTRACK     4 
     179#define ROAR_RPGMODE_TRACKALBUM     5 
    170180 
    171181// Message flags: 
  • libroar/stream.c

    r5542 r5624  
    743743} 
    744744 
     745int roar_stream_get_rpg   (struct roar_connection * con, struct roar_stream * s, struct roar_stream_rpg * rpg) { 
     746 struct roar_message m; 
     747 uint16_t * data = (uint16_t *) m.data; 
     748 size_t i; 
     749 
     750 memset(&m,  0, sizeof(m)); 
     751 
     752 m.cmd     = ROAR_CMD_GET_STREAM_PARA; 
     753 m.stream  = s->id; 
     754 m.datalen = 2*2; 
     755 m.pos     = 0; 
     756 
     757 data[0] = 0; // Version and reserved 
     758 data[1] = ROAR_STREAM_PARA_RPG; // flags 
     759 
     760 for (i = 0; i < m.datalen/2; i++) { 
     761  data[i] = ROAR_HOST2NET16(data[i]); 
     762 } 
     763 
     764 if ( roar_req(con, &m, NULL) == -1 ) 
     765  return -1; 
     766 
     767 if ( m.cmd != ROAR_CMD_OK ) 
     768  return -1; 
     769 
     770 for (i = 0; i < m.datalen/2; i++) { 
     771  data[i] = ROAR_NET2HOST16(data[i]); 
     772 } 
     773 
     774 if ( m.datalen != 10 ) { 
     775  roar_err_set(ROAR_ERROR_MSGSIZE); 
     776  return -1; 
     777 } 
     778 
     779 if ( data[0] != 0 ) { 
     780  roar_err_set(ROAR_ERROR_NSVERSION); 
     781  return -1; 
     782 } 
     783 
     784 if ( data[1] != ROAR_STREAM_PARA_RPG ) { 
     785  roar_err_set(ROAR_ERROR_BADRQC); 
     786  return -1; 
     787 } 
     788 
     789 memset(rpg, 0, sizeof(struct roar_stream_rpg)); 
     790 
     791 rpg->mode = data[2]; 
     792 rpg->mul  = data[3]; 
     793 rpg->div  = data[4]; 
     794 
     795 if ( rpg->mode == 0xFFFF ) 
     796  rpg->mode = -1; 
     797 
     798 return 0; 
     799} 
     800 
     801int roar_stream_set_rpg   (struct roar_connection * con, struct roar_stream * s, const struct roar_stream_rpg * rpg) { 
     802 struct roar_message m; 
     803 uint16_t * data = (uint16_t *) m.data; 
     804 size_t i; 
     805 
     806 memset(&m,  0, sizeof(m)); 
     807 
     808 m.cmd     = ROAR_CMD_SET_STREAM_PARA; 
     809 m.stream  = s->id; 
     810 m.datalen = (2+3)*2; 
     811 m.pos     = 0; 
     812 
     813 data[0] = 0; // Version and reserved 
     814 data[1] = ROAR_STREAM_PARA_RPG; // flags 
     815 data[2] = rpg->mode; 
     816 data[3] = rpg->mul; 
     817 data[4] = rpg->div; 
     818 
     819 for (i = 0; i < m.datalen/2; i++) { 
     820  data[i] = ROAR_HOST2NET16(data[i]); 
     821 } 
     822 
     823 if ( roar_req(con, &m, NULL) == -1 ) 
     824  return -1; 
     825 
     826 if ( m.cmd != ROAR_CMD_OK ) 
     827  return -1; 
     828 
     829 return 0; 
     830} 
    745831 
    746832#ifdef DEBUG 
     
    11681254 
    11691255 return "unknown"; 
     1256} 
     1257 
     1258const char * roar_rpgmode2str(const int rpgmode) { 
     1259 switch (rpgmode) { 
     1260  case ROAR_RPGMODE_DEFAULT:    return "default"; break; 
     1261  case ROAR_RPGMODE_NONE:       return "none"; break; 
     1262  case ROAR_RPGMODE_USER:       return "user"; break; 
     1263  case ROAR_RPGMODE_ALBUM:      return "album"; break; 
     1264  case ROAR_RPGMODE_TRACK:      return "track"; break; 
     1265  case ROAR_RPGMODE_ALBUMTRACK: return "albumtrack"; break; 
     1266  case ROAR_RPGMODE_TRACKALBUM: return "trackalbum"; break; 
     1267  default: 
     1268    roar_err_set(ROAR_ERROR_NOENT); 
     1269    return NULL; 
     1270   break; 
     1271 } 
    11701272} 
    11711273 
  • roarclients/roarctl.c

    r5537 r5624  
    763763 
    764764int display_mixer (struct roar_connection * con, int stream) { 
     765 struct roar_stream_rpg rpg; 
    765766 struct roar_mixer_settings mixer; 
     767 struct roar_stream s; 
    766768 int channels; 
    767769 int i; 
     
    771773  fprintf(stderr, "Error: can not get stream mixer info for stream %i\n", stream); 
    772774  return -1; 
     775 } 
     776 
     777 roar_stream_new_by_id(&s, stream); 
     778 if ( roar_stream_get_rpg(con, &s, &rpg) != -1 ) { 
     779  printf("ReplayGain Mode       : %s\n", roar_rpgmode2str(rpg.mode)); 
    773780 } 
    774781 
  • roard/codecfilter_flac.c

    r5381 r5624  
    116116 const FLAC__StreamMetadata_VorbisComment * vc; 
    117117 FLAC__uint32 i; 
     118 struct roar_stream_rpg rpg; 
    118119 const char * key, * value; 
    119120 char keycopy[ROAR_META_MAX_NAMELEN]; 
    120121 int type; 
    121  float rpg_track = 0, rpg_album = 0; 
     122 float rpg_track = 0, rpg_album = 0, rpg_final = 0; 
    122123 
    123124 if ( metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT ) { 
     
    171172  } 
    172173 
    173  if ( rpg_album ) { 
    174   self->ss->mixer.rpg_div = 2718;  // = int(exp(1)*1000) 
    175   self->ss->mixer.rpg_mul = (float)rpg_album*2718; 
    176  } else if ( rpg_track ) { 
    177   self->ss->mixer.rpg_div = 2718; 
    178   self->ss->mixer.rpg_mul = (float)rpg_track*2718; 
     174 if ( streams_get_rpg(ROAR_STREAM(self->ss)->id, &rpg) != -1 ) { 
     175  rpg_final = 0; 
     176 
     177  switch (rpg.mode) { 
     178   case ROAR_RPGMODE_NONE: rpg_final =  0.; break; 
     179   case ROAR_RPGMODE_USER: rpg_final = -1.; break; 
     180   case ROAR_RPGMODE_ALBUM: rpg_final = rpg_album; break; 
     181   case ROAR_RPGMODE_TRACK: rpg_final = rpg_track; break; 
     182   case ROAR_RPGMODE_ALBUMTRACK: rpg_final = rpg_album ? rpg_album : rpg_track; break; 
     183   case ROAR_RPGMODE_TRACKALBUM: rpg_final = rpg_track ? rpg_track : rpg_album; break; 
     184  } 
     185 
     186  if ( rpg_final > 0 ) { 
     187   self->ss->mixer.rpg_div = 2718; 
     188   self->ss->mixer.rpg_mul = (float)rpg_final*2718; 
     189  } else if ( !rpg_final ) { 
     190   self->ss->mixer.rpg_div = 1; 
     191   self->ss->mixer.rpg_mul = 1; 
     192  } 
    179193 } 
    180194 
  • roard/codecfilter_vorbis.c

    r5381 r5624  
    305305 char key[ROAR_META_MAX_NAMELEN] = {0}, value[LIBROAR_BUFFER_MSGDATA] = {0}; 
    306306 struct roar_stream * s = ROAR_STREAM(self->stream); 
     307 struct roar_stream_rpg rpg; 
    307308 int type; 
    308309 int j, h = 0; 
    309  float rpg_track = 0, rpg_album = 0; 
     310 float rpg_track = 0, rpg_album = 0, rpg_final; 
    310311 int meta_ok; 
    311312 
     
    373374 } 
    374375 
    375  if ( rpg_album ) { 
    376   self->stream->mixer.rpg_div = 2718;  // = int(exp(1)*1000) 
    377   self->stream->mixer.rpg_mul = (float)rpg_album*2718; 
    378  } else if ( rpg_track ) { 
    379   self->stream->mixer.rpg_div = 2718; 
    380   self->stream->mixer.rpg_mul = (float)rpg_track*2718; 
     376 if ( streams_get_rpg(ROAR_STREAM(self->stream)->id, &rpg) != -1 ) { 
     377  rpg_final = 0; 
     378 
     379  switch (rpg.mode) { 
     380   case ROAR_RPGMODE_NONE: rpg_final =  0.; break; 
     381   case ROAR_RPGMODE_USER: rpg_final = -1.; break; 
     382   case ROAR_RPGMODE_ALBUM: rpg_final = rpg_album; break; 
     383   case ROAR_RPGMODE_TRACK: rpg_final = rpg_track; break; 
     384   case ROAR_RPGMODE_ALBUMTRACK: rpg_final = rpg_album ? rpg_album : rpg_track; break; 
     385   case ROAR_RPGMODE_TRACKALBUM: rpg_final = rpg_track ? rpg_track : rpg_album; break; 
     386  } 
     387 
     388  if ( rpg_final > 0 ) { 
     389   self->stream->mixer.rpg_div = 2718; 
     390   self->stream->mixer.rpg_mul = (float)rpg_final*2718; 
     391  } else if ( !rpg_final ) { 
     392   self->stream->mixer.rpg_div = 1; 
     393   self->stream->mixer.rpg_mul = 1; 
     394  } 
    381395 } 
    382396 
  • roard/include/roard.h

    r5414 r5624  
    196196 uint32_t flags; 
    197197 struct { 
    198   uint32_t flags; 
     198  uint32_t                   flags; 
    199199  struct roar_mixer_settings mixer; 
    200200  int                        mixer_channels; 
     201  int                        rpgmode; 
    201202 } streams[ROAR_DIR_DIRIDS]; 
    202203 char * location; 
  • roard/include/streams.h

    r5381 r5624  
    116116 size_t single_sink_c; 
    117117 size_t single_sink_self_c; 
     118 int rpgmode; 
    118119} * g_streams[ROAR_STREAMS_MAX]; 
    119120 
     
    177178int streams_set_map      (int id, char * map, size_t len); 
    178179 
     180int streams_get_rpg      (int id, struct roar_stream_rpg * rpg); 
     181int streams_set_rpg      (int id, const struct roar_stream_rpg * rpg); 
     182 
    179183int streams_ltm_ctl      (int id, int mt, int window, int cmd); 
    180184int streams_ltm_calc     (int id, struct roar_audio_info * info, void * data, size_t len); 
  • roard/req.c

    r5608 r5624  
    11181118 struct roar_audio_info * audio_info; 
    11191119 struct roar_stream_ltm * ltm; 
     1120 struct roar_stream_rpg   rpg; 
    11201121 uint16_t * d  = (uint16_t *) mes->data; 
    11211122 int64_t * d64 = ( int64_t *) mes->data; 
     
    13481349   break; 
    13491350 
     1351  case ROAR_STREAM_PARA_RPG: 
     1352    if ( streams_get_rpg(mes->stream, &rpg) == -1 ) { 
     1353     return -1; 
     1354    } 
     1355 
     1356    mes->datalen = 2*5; 
     1357 
     1358    d[2] = rpg.mode; 
     1359    d[3] = rpg.mul; 
     1360    d[4] = rpg.div; 
     1361 
     1362    for (i = 0; i < mes->datalen/2; i++) { 
     1363     d[i] = ROAR_HOST2NET16(d[i]); 
     1364    } 
     1365   break; 
     1366 
    13501367  default: 
    13511368    ROAR_WARN("req_on_get_stream_para(*): unsupported command: %i", d[1]); 
     
    13601377int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) { 
    13611378 struct roar_stream_server * ss; 
     1379 struct roar_stream_rpg rpg; 
    13621380 uint16_t * d = (uint16_t *) mes->data; 
    13631381 uint32_t tmp, tmp2, flagstore; 
     
    14701488    } 
    14711489   break; 
     1490  case ROAR_STREAM_PARA_RPG: 
     1491    if ( mes->datalen != (5 * 2) ) 
     1492     return -1; 
     1493 
     1494    for (i = 2; i < mes->datalen/2; i++) { 
     1495     d[i] = ROAR_NET2HOST16(d[i]); 
     1496    } 
     1497 
     1498    rpg.mode = d[2]; 
     1499    rpg.mul  = d[3]; 
     1500    rpg.div  = d[4]; 
     1501 
     1502    if ( streams_set_rpg(mes->stream, &rpg) == -1 ) 
     1503     return -1; 
     1504   break; 
    14721505  default: 
    14731506    ROAR_WARN("req_on_set_stream_para(*): unsupported command version: %i, %i", d[0], d[1]); 
  • roard/roard.c

    r5619 r5624  
    523523  g_config->streams[i].mixer.scale    = 65535; 
    524524  g_config->streams[i].mixer.mixer[0] = g_config->streams[i].mixer.scale; 
     525  g_config->streams[i].rpgmode        = ROAR_RPGMODE_ALBUMTRACK; 
    525526 } 
    526527 
  • roard/streams.c

    r5415 r5624  
    234234   s->mixerstream =  NULL; 
    235235#endif 
     236 
     237   s->rpgmode = ROAR_RPGMODE_DEFAULT; 
    236238 
    237239   //roardsp_fchain_init(&(s->fc)); 
     
    15081510} 
    15091511 
     1512int streams_get_rpg      (int id, struct roar_stream_rpg * rpg) { 
     1513 _CHECK_SID(id); 
     1514 
     1515 if ( rpg == NULL ) { 
     1516  roar_err_set(ROAR_ERROR_FAULT); 
     1517  return -1; 
     1518 } 
     1519 
     1520 rpg->mode = g_streams[id]->rpgmode; 
     1521 rpg->mul  = g_streams[id]->mixer.rpg_mul; 
     1522 rpg->div  = g_streams[id]->mixer.rpg_div; 
     1523 
     1524 if ( rpg->mode == ROAR_RPGMODE_DEFAULT ) 
     1525  rpg->mode = g_config->streams[ROAR_STREAM(g_streams[id])->dir].rpgmode; 
     1526 
     1527 return 0; 
     1528} 
     1529 
     1530int streams_set_rpg      (int id, const struct roar_stream_rpg * rpg) { 
     1531 int mode; 
     1532 
     1533 _CHECK_SID(id); 
     1534 
     1535 if ( rpg == NULL ) { 
     1536  roar_err_set(ROAR_ERROR_FAULT); 
     1537  return -1; 
     1538 } 
     1539 
     1540 // test if we have a valid value at all. 
     1541 if ( rpg->mode > ROAR_RPGMODE_TRACKALBUM || rpg->mode < ROAR_RPGMODE_DEFAULT ) { 
     1542  roar_err_set(ROAR_ERROR_RANGE); 
     1543  return -1; 
     1544 } 
     1545 
     1546 mode = g_streams[id]->rpgmode = rpg->mode; 
     1547 
     1548 if ( mode == ROAR_RPGMODE_DEFAULT ) 
     1549  mode = g_config->streams[ROAR_STREAM(g_streams[id])->dir].rpgmode; 
     1550 
     1551 switch (mode) { 
     1552  case ROAR_RPGMODE_NONE: 
     1553    g_streams[id]->mixer.rpg_mul = 1; 
     1554    g_streams[id]->mixer.rpg_div = 1; 
     1555   break; 
     1556  case ROAR_RPGMODE_USER: 
     1557    g_streams[id]->mixer.rpg_mul = rpg->mul; 
     1558    g_streams[id]->mixer.rpg_div = rpg->div; 
     1559   break; 
     1560 } 
     1561 
     1562 return 0; 
     1563} 
     1564 
     1565 
    15101566int streams_ltm_ctl      (int id, int mt, int window, int cmd) { 
    15111567 struct roar_stream_server * ss; 
Note: See TracChangeset for help on using the changeset viewer.